一張圖講解對象鎖和關鍵字synchronized修飾方法(代碼塊)
每個對象在出生的時候就有一把鑰匙(監視器Monitor),那麽被synchronized 修飾的方法相當於給方法加了一個鎖,這個方法就可以進行同步,在多線程的時候,不會出現線程安全問題。
註:Monitor是 Java中用以實現線程之間的互斥與協作的主要手段,它可以看成是對象或者 Class的鎖。每一個對象都有,也僅有一個 Monitor。
下面通過一張圖片進行講解:1.一張圖片圖片看不清,請點擊這裏 : 高清大圖這裏寫圖片描述2.圖片對應的代碼/*** 測試的object類**/}}}}}}12345678910111213141516171819202122232425262728293031323334353637383940414243/*** 測試線程類**/}}}}}}}}}}}}}}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081運行結果:1234註:1、運行的結果可能和上圖講的線程流程不同,沒有關系,只要理解對象鎖和synchronized的核心思想就好,線程的運行本來就是具有隨機性這個特點。
2、此段代碼是同步方法,其實同步的代碼塊也是一個道理,同步代碼塊用synchronized(this)時候,當一個線程訪問object的一個synchronized(this)同步代碼塊的時候,其他線程對object中所有其他的synchronized(www.wmyld11.cn this)同步的代碼塊訪問都被阻塞 (阻塞的是同步代碼塊,線程依然可以進入同步代碼塊的方法)。
3.總結每個對象都有一把鎖(對象監視器),關鍵字synchronized取得鎖都是對象鎖,而不是把一段代碼或方法(函數)當做鎖。
上圖所示,哪個線程先執行帶有synchronized關鍵字的方法,哪個線程就持有這個方法所屬對象的鑰匙。其他線程只能處於等待狀態。
調用關鍵字synchronized聲明的方法,一定是排隊運行的。這才是使用synchronized關鍵字的作用,排隊運行,如果有共享資源的話,那麽共享資源的讀取就是線程安全的。
如果一個線程持有 object的鑰匙,那麽其他線程可以訪問object對象沒有上鎖的方法,也就是非synchronized類型的方法。
和線程關系首先看一下線程和 Monitor之間關系,以 及線程的狀態轉換圖。通過圖講解一下整個過程。
這裏寫圖片描述上圖分為三塊:Entry Set(進入區) 、The Owner(擁有區)、Wait Set(等待區)。
(進入區):表示線程通過synchronized要求獲取對象的鎖。如果對象未被鎖住,則迚入擁有者;否則則在進入區等待。一旦對象鎖被其他線程釋放,立即參與競爭。
(擁有區):表示某一線程成功競爭到對象鎖。
(等待區):表示線程通過對象的wait方法,釋放對象的鎖,並在等待區等待被喚醒。
從圖中可以看出,一個 Monitor在某個時刻,只能被一個線程擁有,該線程就是 “Active www.120xh.cn/ Thread”,而其它線程都是 “Waiting Thread”,分別在兩個隊列 “ Entry Set”和 “Wait Set”裏面等候。
上面的內容講解引自 :Java命令學習系列(二)——www.t1yl1.com/Jstack 中關於Monitor的講解。
5.參考Java多線程編程核心技術如果帥氣(美麗)、睿智(聰穎),和我一樣簡單善良的你看到本篇博文中存在問題,請指出,我虛心接受你讓我成長的批評,謝謝閱讀!
祝你今天開心愉快!
歡迎訪問我的csdn博客,我們一同成長!
“不管做什麽,只要堅持下去就會看到不一樣!在路上,不卑不亢!”
一張圖講解對象鎖和關鍵字synchronized修飾方法(代碼塊)