簡(jiǎn)介
synchronized時(shí)java中的一個(gè)關(guān)鍵字, 用于控制并發(fā), 也是java中的重量級(jí)鎖。synchronized可以保證在同一時(shí)刻,只有一個(gè)線程可以執(zhí)行某個(gè)方法或者某個(gè)代碼塊, 并且保證一個(gè)線程的變化可見(jiàn)(可見(jiàn)性),可代替volatile。
使用方法
- 對(duì)于普通同步方法, 鎖是當(dāng)前實(shí)例對(duì)象。
- 對(duì)于靜態(tài)同步方法, 鎖是當(dāng)前類的Class對(duì)象。
- 對(duì)于同步方法快, 鎖是synchronized括號(hào)里配置的對(duì)象。
原理
JVM規(guī)范規(guī)定,synchronized基于進(jìn)入和退出Monitor對(duì)象來(lái)實(shí)現(xiàn)方法同步和代碼塊同步,但是兩者的實(shí)現(xiàn)細(xì)節(jié)不太一樣。代碼塊同步是用montiorenter和monitorexit指令實(shí)現(xiàn)的,而方法同步是使用其他方式實(shí)現(xiàn)。

monitorenter指令是在編譯后插入到同步代碼塊的開(kāi)始位置,monitorexit指定是插入到方法的結(jié)束處和異常處, JVM會(huì)保證每個(gè)monitorenter都有相應(yīng)的monitorexit與之對(duì)應(yīng)。任務(wù)和一個(gè)對(duì)象都有minitor與之關(guān)聯(lián),當(dāng)且一個(gè)monitor被持有后, 它處于鎖定狀態(tài)。線程運(yùn)行到monitorenter指令時(shí),將會(huì)嘗試獲取對(duì)象所有對(duì)應(yīng)的monitor的控制權(quán),即嘗試獲得對(duì)象的鎖。
synchronized同步方法并沒(méi)有通過(guò)monitorenter和monitorexit來(lái)實(shí)現(xiàn), 而是通過(guò)設(shè)置ACC_SYNCHRONIZED 標(biāo)識(shí), ACC_SYNCHRONIZED 告訴JVM該方法是一個(gè)同步方法,從而執(zhí)行相應(yīng)的同步調(diào)用。
synchronized是可重入鎖, 可重入鎖的意思是線程可以再次獲取自己的內(nèi)部鎖,在同一鎖程中,不需要再次獲取鎖。 每個(gè)對(duì)象擁有一個(gè)計(jì)數(shù)器, 當(dāng)線程擁有鎖后, 計(jì)數(shù)器加一, 線程釋放鎖后, 計(jì)數(shù)器減一。
synchronized特性:

Java對(duì)象頭
synchronized用的鎖存在Java對(duì)象頭里。
鎖的升級(jí)和對(duì)比
Java SE1.6為了減少獲得鎖和四方所帶來(lái)的性能損耗,引入了“偏向鎖”和“輕量級(jí)鎖” 。在Java1.6中, 鎖一共存在4種狀態(tài),級(jí)別從低到高依次是:無(wú)鎖狀態(tài)、偏向鎖狀態(tài)、輕量級(jí)鎖狀態(tài)、重量級(jí)鎖狀態(tài),這幾個(gè)狀態(tài)會(huì)隨著競(jìng)爭(zhēng)情況逐漸升級(jí)。鎖可以升級(jí)不能降級(jí), 目的是為了降低獲得鎖和釋放鎖的效率。
- 偏向鎖
- 輕量級(jí)鎖
- 重量級(jí)鎖