synchronized
? ? ? 在JDK 5之前Java語(yǔ)言是靠synchronized關(guān)鍵字保證同步的,這會(huì)導(dǎo)致有鎖(后面的章節(jié)還會(huì)談到鎖)纺座。
鎖機(jī)制存在以下問(wèn)題:
(1)在多線程競(jìng)爭(zhēng)下息拜,加鎖、釋放鎖會(huì)導(dǎo)致比較多的上下文切換和調(diào)度延時(shí)净响,引起性能問(wèn)題少欺。
(2)一個(gè)線程持有鎖會(huì)導(dǎo)致其它所有需要此鎖的線程掛起。
(3)如果一個(gè)優(yōu)先級(jí)高的線程等待一個(gè)優(yōu)先級(jí)低的線程釋放鎖會(huì)導(dǎo)致優(yōu)先級(jí)倒置馋贤,引起性能風(fēng)險(xiǎn)赞别。
volatile是不錯(cuò)的機(jī)制,但是volatile不能保證原子性配乓。因此對(duì)于線程同步最終還是要回到鎖機(jī)制上來(lái)仿滔。
synchronized實(shí)現(xiàn)同步的基礎(chǔ):Java中的每一個(gè)對(duì)象都可以作為鎖惠毁。具體表現(xiàn)為以下3種形式。?
?對(duì)于普通同步方法崎页,鎖是當(dāng)前實(shí)例對(duì)象鞠绰。?
?對(duì)于靜態(tài)同步方法,鎖是當(dāng)前類的Class對(duì)象飒焦。??
?對(duì)于同步方法塊蜈膨,鎖是Synchonized括號(hào)里配置的對(duì)象。
? ? ? 獨(dú)占鎖是一種悲觀鎖荒给,synchronized就是一種獨(dú)占鎖丈挟,會(huì)導(dǎo)致其它所有需要鎖的線程掛起,等待持有鎖的線程釋放鎖 .從javaSE 1.6之后志电,為了減少獲得鎖和釋放鎖帶來(lái)的性能消耗曙咽,引入了“偏向鎖”和“輕量級(jí)鎖”.自此,鎖一共有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í)鎖后不能降級(jí)成偏向鎖魁亦。這種鎖升級(jí)卻不能降級(jí)的策略渔隶,目的是為了提高獲得鎖和釋放鎖的效率. 這幾種鎖各自特性如下:
提到了自旋的概念,也順帶提下:
自旋鎖的概念
首先是一種鎖洁奈,與互斥鎖相似间唉,基本作用是用于線程(進(jìn)程)之間的同步。與普通鎖不同的是利术,一個(gè)線程A在獲得普通鎖后呈野,如果再有線程B試圖獲取鎖,那么這個(gè)線程B將會(huì)掛起(阻塞)印叁;試想下被冒,如果兩個(gè)線程資源競(jìng)爭(zhēng)不是特別激烈,而處理器阻塞一個(gè)線程引起的線程上下文的切換的代價(jià)高于等待資源的代價(jià)的時(shí)候(鎖的已保持者保持鎖時(shí)間比較短)轮蜕,那么線程B可以不放棄CPU時(shí)間片昨悼,而是在“原地”忙等,直到鎖的持有者釋放了該鎖肠虽,這就是自旋鎖的原理幔戏,可見(jiàn)自旋鎖是一種非阻塞鎖。
二税课、自旋鎖可能引起的問(wèn)題:
1.占據(jù)CPU時(shí)間過(guò)長(zhǎng):如果鎖的當(dāng)前持有者長(zhǎng)時(shí)間不釋放該鎖闲延,那么等待者將長(zhǎng)時(shí)間的占據(jù)cpu時(shí)間片痊剖,導(dǎo)致CPU資源的浪費(fèi),因此可以設(shè)定一個(gè)時(shí)間垒玲,當(dāng)鎖持有者超過(guò)這個(gè)時(shí)間不釋放鎖時(shí)陆馁,等待者會(huì)放棄CPU時(shí)間片阻塞;
2.容易引發(fā)死鎖問(wèn)題:試想一下合愈,有一個(gè)線程連續(xù)兩次試圖獲得自旋鎖(比如在遞歸程序中)叮贩,第一次這個(gè)線程獲得了該鎖,當(dāng)?shù)诙卧噲D加鎖的時(shí)候佛析,檢測(cè)到鎖已被占用(其實(shí)是被自己占用)益老,那么這時(shí),線程會(huì)一直等待自己釋放該鎖寸莫,而不能繼續(xù)執(zhí)行捺萌,這樣就引起了死鎖。因此遞歸程序使用自旋鎖應(yīng)該遵循以下原則:遞歸程序決不能在持有自旋鎖時(shí)調(diào)用它自己膘茎,也決不能在遞歸調(diào)用時(shí)試圖獲得相同的自旋鎖桃纯。
volatile的定義:
Java語(yǔ)言規(guī)范第3版中對(duì)volatile的定義如下:Java編程語(yǔ)言允許線程訪問(wèn)共享變量,為了確保共享變量能被準(zhǔn)確和一致地更新披坏,線程應(yīng)該確保通過(guò)排他鎖單獨(dú)獲得這個(gè)變量态坦。Java語(yǔ)言提供了volatile,在某些情況下比鎖要更加方便棒拂。如果一個(gè)字段被聲明成volatile伞梯,Java線程內(nèi)存模型確保所有線程看到這個(gè)變量的值是一致的。
1.volatile是輕量級(jí)的synchronized帚屉,它在多處理器開(kāi)發(fā)中保證了共享變量的“可見(jiàn)性”壮锻。可見(jiàn)性的意思是當(dāng)一個(gè)線程修改一個(gè)共享變量時(shí)涮阔,另外一個(gè)線程能讀到這個(gè)修改的值.
2.volatile比synchronized的使用和執(zhí)行成本更低,因?yàn)樗粫?huì)引起線程上下文的切換和調(diào)度灰殴。