關於synchronized,“鎖住了誰”

stu_wei發表於2018-01-07

突然,我遇到了sychronized關鍵字。

“對它的理解模模糊糊,似懂非懂”,這是我之前的感覺,但是百度了一波後,發現我對它真的是一無所知。

(前言)sychronized應用最常見的地方:1,sychronized方法;2,sychronized程式碼塊。(這裡先不討論static關鍵字的東西,因為很多大手已經解釋得很好了,不再費口舌,本文所有程式碼都預設為非靜態。)sychronized程式碼塊又有兩種情況:1,sychronized(this);2,sychronized(object)。所以,其實sychronized最常見的“用法”有三點。

問題:鎖住了誰?

最初,我以為sychronized方法是鎖住了方法,任何執行到那個方法的執行緒都會進入阻塞態;sychronized(this)鎖住了程式碼塊所在的方法所在的物件,任何執行到那個物件的執行緒都會進入阻塞態;sychronized(object)鎖住了object,任何執行到object的執行緒都會進入阻塞態。

事實並不是這樣,可能很多人要牢騷了,既然不是這樣,為什麼還要費口舌,難道是為了誤導?或者僅僅是記錄自己原來的錯誤理解?當然我要為自己洗白:其實我的錯誤雖然沒發生在你身上,但是有可能發生在其他人身上,其實我百度了好長時間,發現確實有很多人都是這麼理解的,而且評論席裡還有各種“666”,所以,可能你身邊很多人對synchronized的理解都是不太恰當的,我們都不是獨立完成整個專案的開發者,知道別人潛在的錯誤是很重要的。

其實前兩種“用法”大家的意見都比較統一:sychronized方法和synchronized(this)鎖住的是方法所屬物件的所有synchronized方法和synchronized(this)程式碼塊。這裡,很多人強調“並不是鎖住了程式碼而是鎖住了物件”,但是我不知道這句話的“實際意義”是什麼,我也沒看明白他們為什麼要強調,反而我感覺這種強調是在咬文嚼字以致更難理解。實際上,當一個執行緒進入到synchronized方法或synchronized(this)時,並不是其他執行緒“呼叫此物件時一定會進入阻塞態”,其他執行緒呼叫此物件的非sychronized方法或非synchronized程式碼塊都會順利執行,不會進入阻塞態,而“其他執行緒呼叫此物件的synchronized方法或者synchronized(this)程式碼塊會進入阻塞態”。synchronized(this)和synchronized方法一樣,只是synchronized(this)的鎖定範圍“更精確一些”。應用場景不同,但是鎖住的東西是一樣的。

到這裡,問題就集中在synchronized(object)鎖住了誰?這也是我之前一直疑惑的地方。

上碼,快準狠。(百度了好長時間,卻一直沒想過自己實驗,實在沒辦法了,才去動手碼字,發現比看一百篇軟文有用多了)。

……

經過實驗,發現,synchronized(object)鎖住的是“當前物件的synchronized(object)程式碼塊”,這句話看起來真的很像廢話。但是卻有太多人沒弄明白,其實真相是如此簡單。它包含了兩個條件:1,當前物件;2,synchronized(object)程式碼塊。經過實驗,我發現:當一個執行緒進入synchronized(object)時,其他執行緒是可以進入其他synchronized方法或者synchronized(this)程式碼塊的,而且,當一個執行緒進入synchronized方法或者synchronized方法時,其他執行緒也可以進入synchronized(object)程式碼塊。這說明synchronized(object)和其他兩種情況是不一樣的,很多人都遺漏了這一點,以為是鎖住了object。

語言是強大的,是我的信仰,但是我並不能很好的運用,至少在這個問題上,我並不能用語言表達我的理解,也建議各位遇到問題時,百度雖是第一選擇,但有些問題,動手碼字,把自己想法種的可能性碼出來,執行一下,所有東西都會更清晰且真實的展現出來。

相關文章