<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    java技術(shù)研究

    統(tǒng)計(jì)

    留言簿(3)

    閱讀排行榜

    評(píng)論排行榜

    Lock和synchronized (轉(zhuǎn))

        JDK1.5以后,在鎖機(jī)制方面引入了新的鎖-Lock,在網(wǎng)上的說法都比較籠統(tǒng),結(jié)合網(wǎng)上的信息和我的理解這里做個(gè)總結(jié)。 

        java現(xiàn)有的鎖機(jī)制有兩種實(shí)現(xiàn)方式,J.DK1.4前是通過synchronized實(shí)現(xiàn),JDK1.5后加入java.util.concurrent.locks包下的各種lock(以下簡稱Lock) 

        先說說代碼層的區(qū)別。 
        synchronized:在代碼里,synchronized類似“面向?qū)ο?#8221;,修飾類、方法、對象。 
        Lock:不作為修飾,類似“面向過程”,在方法中需要鎖的時(shí)候lock,在結(jié)束的時(shí)候unlock(一般都在finally塊里)。 
    例如代碼: 

    Java代碼  收藏代碼
    1. public void method1() {  
    2.     synchronized(this){//舊鎖,無需人工釋放  
    3.         System.out.println(1);  
    4.     }  
    5. }  
    6.       
    7. public void method2() {  
    8.     Lock lock = new ReentrantLock();  
    9.     lock.lock();//上鎖  
    10.     try{  
    11.         System.out.println(2);  
    12.     }finally{  
    13.         lock.unlock();//解鎖  
    14.     }  
    15. }  

        其次說說性能。 
        相關(guān)的性能測試網(wǎng)上已經(jīng)有很多,這里也直接拿來主義,給出結(jié)論: 
        在并發(fā)高是,luck性能優(yōu)勢很明顯,在低并發(fā)時(shí),synchronized也能取得優(yōu)勢。具體的臨界范圍比較難定論,下面會(huì)討論。 

        現(xiàn)在來分析它們具體的區(qū)別。 
        鎖都是 原子性 的,也可以理解為鎖是否在使用的標(biāo)記,并且比較和設(shè)置這個(gè)標(biāo)記的操作是原子性的,不同硬件平臺(tái)上的jdk實(shí)現(xiàn)鎖的相關(guān)方法都是native的(比如park/unpark),所以不同平臺(tái)上鎖的精確度的等級(jí)由這些native的方法決定。所以網(wǎng)上經(jīng)常可以看見的結(jié)論是“Lock比synchronized有更精確的原子操作”說的也是native方法(不得不感慨C才是硬件王道)。 


    下面繼續(xù)討論怎么由代碼層到native的過程。 
    1、所有對象都自動(dòng)含有單一的鎖,JVM負(fù)責(zé)跟蹤對象被加鎖的次數(shù)。如果一個(gè)對象被解鎖,其計(jì)數(shù)變?yōu)?。在任務(wù)(線程)第一次給對象加鎖的時(shí)候,計(jì)數(shù)變?yōu)?。每當(dāng)這個(gè)相同的任務(wù)(線程)在此對象上獲得鎖時(shí),計(jì)數(shù)會(huì)遞增。 只有首先獲得鎖的任務(wù)(線程)才能繼續(xù)獲取該對象上的多個(gè)鎖。每當(dāng)任務(wù)離開時(shí),計(jì)數(shù)遞減,當(dāng)計(jì)數(shù)為0的時(shí)候,鎖被完全釋放。synchronized就是基于這個(gè)原理,同時(shí)synchronized靠某個(gè)對象的單一鎖技術(shù)的次數(shù)來判斷是否被鎖,所以無需(也不能)人工干預(yù)鎖的獲取和釋放。如果結(jié)合方法調(diào)用時(shí)的棧和框架(如果對方法的調(diào)用過程不熟悉建議看看http://wupuyuan.iteye.com/blog/1157548),不難推測出synchronized原理是基于棧中的某對象來控制一個(gè)框架,所以對于synchronized有常用的優(yōu)化是鎖對象不鎖方法。實(shí)際上synchronized作用于方法時(shí),鎖住的是“this”,作用于靜態(tài)方法/屬性時(shí),鎖住的是存在于永久帶的CLASS,相當(dāng)于這個(gè)CLASS的全局鎖,鎖作用于一般對象時(shí),鎖住的是對應(yīng)代碼塊。在HotSpot中JVM實(shí)現(xiàn)中,鎖有個(gè)專門的名字:對象監(jiān)視器。 


    當(dāng)多個(gè)線程同時(shí)請求某個(gè)對象監(jiān)視器時(shí),對象監(jiān)視器會(huì)設(shè)置幾種狀態(tài)用來區(qū)分請求的線程 
    Contention List:所有請求鎖的線程將被首先放置到該競爭隊(duì)列,是個(gè)虛擬隊(duì)列,不是實(shí)際的Queue的數(shù)據(jù)結(jié)構(gòu)。
    Entry List:EntryList與ContentionList邏輯上同屬等待隊(duì)列,ContentionList會(huì)被線程并發(fā)訪問,為了降低對ContentionList隊(duì)尾的爭用,而建立EntryList。,Contention List中那些有資格成為候選人的線程被移到Entry List 
    Wait Set:那些調(diào)用wait方法被阻塞的線程被放置到Wait Set 
    OnDeck:任何時(shí)刻最多只能有一個(gè)線程正在競爭鎖,該線程稱為OnDeck 
    Owner:獲得鎖的線程稱為Owner 
    !Owner:釋放鎖的線程 

    2、Lock不同于synchronized面向?qū)ο螅跅V械目蚣芏皇悄硞€(gè)具體對象,所以Lock只需要在棧里設(shè)置鎖的開始和結(jié)束(lock和unlock)的地方就行了(人工必須標(biāo)明),不用關(guān)心框架大小對象的變化等等。這么做的好處是Lock能提供無條件的、可輪詢的、定時(shí)的、可中斷的鎖獲取操作,相對于synchronized來說,synchronized的鎖的獲取是釋放必須在一個(gè)模塊里,獲取和釋放的順序必須相反,而Lock則可以在不同范圍內(nèi)獲取釋放,并且順序無關(guān)。java.util.concurrent.locks下的鎖類很類似,依賴于java.util.concurrent.AbstractQueuedSynchronizer,它們把所有的Lock接口操作都轉(zhuǎn)嫁到Sync類上,這個(gè)類繼承了AbstractQueuedSynchronizer,它同時(shí)還包含子2個(gè)類:NonfairSync 和FairSync 從名字上可以看的出是為了實(shí)現(xiàn)公平和非公平性。AbstractQueuedSynchronizer中把所有的的請求線程構(gòu)成一個(gè)隊(duì)列(一樣也是虛擬的),具體的實(shí)現(xiàn)可以參考http://blog.csdn.net/chen77716/article/details/6641477#,這里我就不復(fù)制了。 

    3、從jdk的源代碼來看,Lock和synchronized的源碼基本相同,區(qū)別主要在維護(hù)的同步隊(duì)列上。再往下深究就到了native方法了。 

    4、還有個(gè)改進(jìn)我也想說下,其實(shí)很重要的。線程分阻塞(wait)和非阻塞狀態(tài),阻塞狀態(tài)由操作系統(tǒng)(linux、windows等)完成,當(dāng)前一個(gè)被“鎖”的線程執(zhí)行完畢后,有可能在后續(xù)的線程隊(duì)列里還沒分配出一個(gè)獲取鎖而被“喚醒”的非阻塞線程,即所有線程還都是阻塞狀態(tài)時(shí),就被系統(tǒng)調(diào)度(進(jìn)入內(nèi)核的線程是阻塞的),這樣會(huì)導(dǎo)致內(nèi)核在用戶態(tài)和內(nèi)核態(tài)之間來回接換,嚴(yán)重影響鎖的性能。在jdk1.6以前主要靠自旋鎖來解決,原理是在前一個(gè)線程結(jié)束后,爭用線程可以做一個(gè)空循環(huán),繼續(xù)占有CPU,等待取鎖的機(jī)會(huì)。當(dāng)然這樣做顯然也是浪費(fèi)時(shí)間,只是在兩種浪費(fèi)中選取浪費(fèi)少的……  jdk1.6后引入了偏向鎖,當(dāng)線程第一次獲得了監(jiān)視對象,之后讓監(jiān)視對象“偏向”這個(gè)線程,之后的多次調(diào)用則可以避免CAS操作,等于是置了一臨時(shí)變量來記錄位置(類似索引比較)。詳細(xì)的就涉及到匯編指令了,我也就沒太深究,偏向鎖性能優(yōu)于自旋鎖,但是還是沒有達(dá)到HotSpot認(rèn)為的最佳時(shí)間(一個(gè)線程上下文切換的時(shí)間)。 

        綜合來看對于所有的高并發(fā)情況,采用Lock加鎖是最優(yōu)選擇,但是由于歷史遺留等問題,synchronized也還是不能完全被淘汰,同時(shí),在低并發(fā)情況下,synchronized的性能還是比Lock好的。 

    原帖地址:http://wupuyuan.iteye.com/blog/1158655

    posted on 2015-10-27 19:08 小秦 閱讀(320) 評(píng)論(0)  編輯  收藏


    只有注冊用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 久久精品国产亚洲av影院| 免费不卡视频一卡二卡| 又粗又硬免费毛片| 亚洲国产精品自在自线观看| 免费精品人在线二线三线区别| 亚洲第一二三四区| 国产精品久久久久免费a∨| 亚洲精品第一国产综合精品| 亚洲一区在线免费观看| 亚洲国产午夜精品理论片| 在线视频观看免费视频18| 亚洲日本人成中文字幕| 午夜免费福利在线观看| 美女被免费网站在线视频免费| 免费欧洲毛片A级视频无风险| 特级毛片aaaa级毛片免费| 黑人大战亚洲人精品一区| 无码免费一区二区三区免费播放 | 9277手机在线视频观看免费| 亚洲激情中文字幕| 无人在线观看免费高清视频| 亚洲成AV人片高潮喷水| 亚洲人成色77777在线观看大| 西西人体免费视频| 亚洲欧洲日产国码在线观看| 成全影视免费观看大全二| 免费国产高清毛不卡片基地| 亚洲综合在线另类色区奇米| 精品熟女少妇a∨免费久久| 亚洲午夜精品久久久久久app| 免费成人在线观看| 久久精品成人免费网站| 亚洲一级视频在线观看| 亚洲av无码成人精品区在线播放| 国产真人无码作爱视频免费| 亚洲1234区乱码| 亚洲国产一区二区视频网站| 91av免费观看| 国产亚洲综合久久| 337p欧洲亚洲大胆艺术| 国产成人高清精品免费软件|