Java並發編程最常用和易用的技術莫過於synchronized關鍵字,而Scala的並發編程之旅也可以從synchronized開始。而synchronized的背后其實是monitor技術。
第一節:什么是Monitor
Monitor是解決並發編程問題的一種常用技術,可以有效解決互斥和同步兩大常見問題,通常翻譯為‘監視器’或‘管程’。‘管程‘更能表達monitor的含義,指的是管理共享變量以及對共享變量的操作過程,讓他們支持並發。
第二節:Scala的synchronized
Synchronized是Java對monitor的實現,可以對代碼塊或方法使用,使得每次只能有一個線程訪問,實現了線程互斥。當一個線程獲取了鎖,其他線程將在隊列上等待,實現了線程同步。
Scala延用了這一關鍵字,但是語法有所不同。
//用於代碼塊 obj.synchronized { ... } //用於方法 def func(): Unit = this.synchronized { ... }
跟Java一樣,這里的this是可以省略的,因為默認加鎖的對象就是this,但是不建議省略。
第三節:Scala實例
import java.util.concurrent.TimeUnit object SynchronizedDemo { private var inc: Int = 0 def addOne(): Unit = this.synchronized { TimeUnit.SECONDS.sleep(1) inc = 1 } def main(args: Array[String]): Unit = { for (i <- 1 to 10) { new Thread { override def run(): Unit = { println(s"run thread with object method $i") addOne() } }.start() } val instance = new SynchronizedDemo for (i <- 1 to 10) { new Thread { override def run(): Unit = { println(s"run thread with class method $i") instance.addOne() } }.start() } while (true) { println(s"object inc=$inc, class inc=${instance.inc}") TimeUnit.SECONDS.sleep(1) } } } class SynchronizedDemo { private var inc: Int = 0 def addOne(): Unit = this.synchronized { TimeUnit.SECONDS.sleep(1) inc = 1 } }
程序輸出
run thread with class method 7 run thread with class method 4 run thread with object method 8 run thread with object method 7 run thread with class method 10 run thread with class method 8 run thread with class method 9 run thread with object method 5 run thread with object method 3 run thread with object method 2 run thread with object method 4 run thread with object method 10 run thread with object method 9 run thread with class method 5 run thread with class method 3 object inc=0, class inc=0 run thread with object method 1 run thread with class method 6 run thread with class method 1 run thread with class method 2 run thread with object method 6 object inc=1, class inc=1 object inc=2, class inc=2 object inc=3, class inc=2 object inc=4, class inc=4 object inc=5, class inc=5 object inc=6, class inc=6 object inc=7, class inc=7 object inc=8, class inc=8 object inc=9, class inc=9 object inc=10, class inc=10
解析
- 在object SynchronizedDemo和class SynchronizedDemo中均定義了一個inc變量和一個addOne方法,addOne方法的作用就是將inc加1。
- main方法中,分別創建10個線程調用addOne方法,對inc進行10次加1操作。
- 因為inc變量不是線程安全的,所以對addOne方法加上synchronized關鍵字,使得修改操作是線程安全的。這樣才能保證inc會從1加到10。
- object和class中的this並不相同,object中的this指向的是名為SynchronizedDemo的object對象,class中的則是該class實例化后的對象。(Scala中沒有靜態類和靜態方法,object SynchronizedDemo實際上是創建名為SynchronizedDemo的單例對象)
如果把class中定義的addOne改成如下:
def addOne(): Unit = SynchronizedDemo.synchronized { TimeUnit.SECONDS.sleep(1) inc = 1 }
兩處定義的addOne方法就會互斥,輸出就會變成如下:
run thread with object method 2 run thread with object method 1 run thread with object method 3 run thread with object method 4 run thread with object method 5 run thread with object method 6 run thread with object method 7 run thread with object method 8 run thread with object method 9 run thread with object method 10 run thread with class method 1 run thread with class method 2 run thread with class method 3 run thread with class method 4 run thread with class method 5 run thread with class method 6 run thread with class method 7 run thread with class method 8 run thread with class method 9 run thread with class method 10 object inc=0, class inc=0 object inc=1, class inc=0 object inc=1, class inc=1 object inc=1, class inc=2 object inc=1, class inc=3 object inc=1, class inc=4 object inc=1, class inc=5 object inc=1, class inc=6 object inc=1, class inc=7 object inc=1, class inc=8 object inc=1, class inc=9 object inc=1, class inc=10 object inc=2, class inc=10 object inc=3, class inc=10 object inc=4, class inc=10 object inc=5, class inc=10 object inc=6, class inc=10 object inc=7, class inc=10 object inc=8, class inc=10 object inc=9, class inc=10 object inc=10, class inc=10