偏向鎖
在大多數(shù)情況下,鎖不僅不存在多線程競爭矮湘,而且總是由同一線程多次獲得斟冕,因此為了減少同一線程獲取鎖(會涉及到一些CAS操作,耗時(shí))的代價(jià)而引入偏向鎖。
使用場景缅阳,一般是一個線程訪問同步塊磕蛇,優(yōu)點(diǎn)是加鎖解鎖不需要額外的 消耗
1、線程訪問同步代碼塊 判斷當(dāng)前鎖狀態(tài)十办,鎖標(biāo)志位01孤里,再判斷是否是偏向鎖 ,是否偏向鎖為1 則是偏向鎖橘洞;
2捌袜、是偏向鎖,再判斷對象頭中Markwork記錄的ThreadId是否是當(dāng)前線程炸枣;
????????如果是虏等,當(dāng)前線程直接獲取到偏向鎖弄唧,繼續(xù)執(zhí)行同步塊代碼;
? ? ? ? 如果不是霍衫,則通過CAS操作候引,嘗試將對象頭中Markwork中的ThreadID更新為自己的線程id,來獲取偏向鎖 敦跌,當(dāng)CAS操作成功澄干,線程拿到了偏向鎖,則繼續(xù)執(zhí)行同步塊代碼柠傍;當(dāng)CAS操作失敗麸俘,開始對原線程持有的偏向鎖撤銷,當(dāng)原持有偏向鎖 的線程到達(dá)安全點(diǎn)后惧笛,停止原持有偏向鎖的線程从媚;
3、原持有偏向鎖線程的活動狀態(tài)患整,如果已經(jīng)退出同步塊代碼拜效,則喚起新的線程來競爭偏向鎖,對象重新偏向各谚;如果是原持有偏向鎖線程沒有退出同步塊紧憾,則升級輕量級鎖;
輕量級鎖
由于出現(xiàn)鎖的競爭昌渤,會將偏向鎖升級為輕量級鎖
1赴穗、升級輕量級鎖 之前,線程會在線程棧中分配鎖記錄存儲空間愈涩;
2望抽、拷貝對象頭中Markwork的鎖信息封裝為LockRecord到線程棧的鎖記錄中加矛;
3履婉、通過CAS操作,將線程棧中的分配鎖記錄的指針地址更新到對象頭的Markwork中斟览,如果更新成功毁腿,獲取輕量級鎖;
4苛茂、如果CAS操作失敗已烤,則利用自旋來嘗試重新獲取輕量級鎖,自旋其實(shí)就是不斷的循環(huán)進(jìn)行CAS操作直到能成功替換妓羊,所以輕量級鎖又叫自旋鎖胯究;
5、lockrecord的作用:在這里實(shí)現(xiàn)了鎖重入躁绸,每當(dāng)同一個線程多次獲取同一個鎖時(shí)裕循,會在當(dāng)前棧幀中放入一個lockrecord臣嚣,但是重入是放入的lockrecord關(guān)于鎖信息的內(nèi)容為null,代表鎖重入剥哑。當(dāng)輕量級解鎖時(shí)硅则,每解鎖一次則從棧幀中彈出一個lockrecord,直到為0株婴;
6怎虫、當(dāng)自旋到一定次數(shù)之后,還是拿不到鎖困介,鎖再次升級大审,升級為重量級鎖。
重量級鎖
在重量級鎖中將LockRecord對象替換為了monitor對象的實(shí)現(xiàn)逻翁。主要通過monitorenter和monitorexit兩個指令來實(shí)現(xiàn)饥努。需要經(jīng)過系統(tǒng)調(diào)用,在并發(fā)低的情況下效率會低八回。
幾種鎖的優(yōu)缺點(diǎn)
總結(jié)
只有一個線程進(jìn)入臨界區(qū) -------偏向鎖
多個線程交替進(jìn)入臨界區(qū)--------輕量級鎖
多個線程同時(shí)進(jìn)入臨界區(qū)-------重量級鎖