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

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

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

    xylz,imxylz

    關(guān)注后端架構(gòu)、中間件、分布式和并發(fā)編程

       :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      111 隨筆 :: 10 文章 :: 2680 評(píng)論 :: 0 Trackbacks

     

    主要談?wù)勬i的性能以及其它一些理論知識(shí),內(nèi)容主要的出處是《Java Concurrency in Practice》,結(jié)合自己的理解和實(shí)際應(yīng)用對(duì)鎖機(jī)制進(jìn)行一個(gè)小小的總結(jié)。

     

    首先需要強(qiáng)調(diào)的一點(diǎn)是:所有鎖(包括內(nèi)置鎖和高級(jí)鎖)都是有性能消耗的,也就是說在高并發(fā)的情況下,由于鎖機(jī)制帶來的上下文切換、資源同步等消耗是非常可觀的。在某些極端情況下,線程在鎖上的消耗可能比線程本身的消耗還要多。所以如果可能的話,在任何情況下都盡量少用鎖,如果不可避免那么采用非阻塞算法是一個(gè)不錯(cuò)的解決方案,但是卻也不是絕對(duì)的。

     

    內(nèi)部鎖

    Java語(yǔ)言通過synchronized關(guān)鍵字來保證原子性。這是因?yàn)槊恳粋€(gè)Object都有一個(gè)隱含的鎖,這個(gè)也稱作監(jiān)視器對(duì)象。在進(jìn)入synchronized之前自動(dòng)獲取此內(nèi)部鎖,而一旦離開此方式(不管通過和中方式離開此方法)都會(huì)自動(dòng)釋放鎖。顯然這是一個(gè)獨(dú)占鎖,每個(gè)鎖請(qǐng)求之間是互斥的。相對(duì)于前面介紹的眾多高級(jí)鎖(Lock/ReadWriteLock等),synchronized的代價(jià)都比后者要高。但是synchronized的語(yǔ)法比較簡(jiǎn)單,而且也比較容易使用和理解,不容易寫法上的錯(cuò)誤。而我們知道Lock一旦調(diào)用了lock()方法獲取到鎖而未正確釋放的話很有可能就死鎖了。所以Lock的釋放操作總是跟在finally代碼塊里面,這在代碼結(jié)構(gòu)上也是一次調(diào)整和冗余。另外前面介紹中說過Lock的實(shí)現(xiàn)已經(jīng)將硬件資源用到了極致,所以未來可優(yōu)化的空間不大,除非硬件有了更高的性能。但是synchronized只是規(guī)范的一種實(shí)現(xiàn),這在不同的平臺(tái)不同的硬件還有很高的提升空間,未來Java在鎖上的優(yōu)化也會(huì)主要在這上面。

     

    性能

    由于鎖總是帶了性能影響,所以是否使用鎖和使用鎖的場(chǎng)合就變得尤為重要。如果在一個(gè)高并發(fā)的Web請(qǐng)求中使用了強(qiáng)制的獨(dú)占鎖,那么就可以發(fā)現(xiàn)Web的吞吐量將急劇下降。

    為了利用并發(fā)來提高性能,出發(fā)點(diǎn)就是:更有效的利用現(xiàn)有的資源,同時(shí)讓程序盡可能的開拓更多可用的資源。這意味著機(jī)器盡可能的處于忙碌的狀態(tài),通常意義是說CPU忙于計(jì)算,而不是等待。當(dāng)然CPU要做有用的事情,而不是進(jìn)行無謂的循環(huán)。當(dāng)然在實(shí)踐中通常會(huì)預(yù)留一些資源出來以便應(yīng)急特殊情況,這在以后的線程池并發(fā)中可以看到很多例子。

     

    線程阻塞

    鎖機(jī)制的實(shí)現(xiàn)通常需要操作系統(tǒng)提供支持,顯然這會(huì)增加開銷。當(dāng)鎖競(jìng)爭(zhēng)的時(shí)候,失敗的線程必然會(huì)發(fā)生阻塞。JVM既能自旋等待(不斷嘗試,知道成功,很多CAS就是這樣實(shí)現(xiàn)的),也能夠在操作系統(tǒng)中掛起阻塞的線程,直到超時(shí)或者被喚醒。通常情況下這取決于上下文切換的開銷以及與獲取鎖需要等待的時(shí)間二者之間的關(guān)系。自旋等待適合于比較短的等待,而掛起線程比較適合那些比較耗時(shí)的等待。

    掛起一個(gè)線程可能是因?yàn)闊o法獲取到鎖,或者需要某個(gè)特定的條件,或者耗時(shí)的I/O操作。掛起一個(gè)線程需要兩次額外的上下文切換以及操作系統(tǒng)、緩存等多資源的配合:如果線程被提前換出,那么一旦拿到鎖或者條件滿足,那么又需要將線程換回執(zhí)行隊(duì)列,這對(duì)線程而言,兩次上下文切換可能比較耗時(shí)。

     

    鎖競(jìng)爭(zhēng)

    影響鎖競(jìng)爭(zhēng)性的條件有兩個(gè):鎖被請(qǐng)求的頻率和每次持有鎖的時(shí)間。顯然當(dāng)而這二者都很小的時(shí)候,鎖競(jìng)爭(zhēng)不會(huì)成為主要的瓶頸。但是如果鎖使用不當(dāng),導(dǎo)致二者都比較大,那么很有可能CPU不能有效的處理任務(wù),任務(wù)被大量堆積。

    所以減少鎖競(jìng)爭(zhēng)的方式有下面三種:

    1. 減少鎖持有的時(shí)間
    2. 減少鎖請(qǐng)求的頻率
    3. 采用共享鎖取代獨(dú)占鎖

     

    死鎖

    如果一個(gè)線程永遠(yuǎn)不釋放另外一個(gè)線程需要的資源那么就會(huì)導(dǎo)致死鎖。這有兩種情況:一種情況是線程A永遠(yuǎn)不釋放鎖,結(jié)果B一直拿不到鎖,所以線程B就“死掉”了;第二種情況下,線程A擁有線程B需要的鎖Y,同時(shí)線程B擁有線程A需要的鎖X,那么這時(shí)候線程A/B互相依賴對(duì)方釋放鎖,于是二者都“死掉”了。

    還有一種情況為發(fā)生死鎖,如果一個(gè)線程總是不能被調(diào)度,那么等待此線程結(jié)果的線程可能就死鎖了。這種情況叫做線程饑餓死鎖。比如說在前面介紹的非公平鎖中,如果某些線程非常活躍,在高并發(fā)情況下這類線程可能總是拿到鎖,那么那些活躍度低的線程可能就一直拿不到鎖,這樣就發(fā)生了“饑餓死”。

    避免死鎖的解決方案是:盡可能的按照鎖的使用規(guī)范請(qǐng)求鎖,另外鎖的請(qǐng)求粒度要小(不要在不需要鎖的地方占用鎖,鎖不用了盡快釋放);在高級(jí)鎖里面總是使用tryLock或者定時(shí)機(jī)制(這個(gè)以后會(huì)講,就是指定獲取鎖超時(shí)的時(shí)間,如果時(shí)間到了還沒有獲取到鎖那么就放棄)。高級(jí)鎖(Lock)里面的這兩種方式可以有效的避免死鎖。

     

    活鎖

    活鎖描述的是線程總是嘗試某項(xiàng)操作卻總是失敗的情況。這種情況下盡管線程沒有被阻塞,但是人物卻總是不能被執(zhí)行。比如在一個(gè)死循環(huán)里面總是嘗試做某件事,結(jié)果卻總是失敗,現(xiàn)在線程將永遠(yuǎn)不能跳出這個(gè)循環(huán)。另外一種情況是在一個(gè)隊(duì)列中每次從隊(duì)列頭取出一個(gè)任務(wù)來執(zhí)行,每次都失敗,然后將任務(wù)放入隊(duì)列頭,接下來再一次從隊(duì)列頭取出任務(wù)執(zhí)行,仍然失敗。

    還有一種活鎖方式發(fā)生在“碰撞協(xié)讓”情況下:兩個(gè)人過獨(dú)木橋,如果在半路相撞,雙方禮貌退出去然后再試一次。如果總是失敗,那么這兩個(gè)任務(wù)將一直無法得到執(zhí)行。

     

    總之解決鎖問題的關(guān)鍵就是:從簡(jiǎn)單的開始,先保證正確,然后再開始優(yōu)化。

     

     



    ©2009-2014 IMXYLZ |求賢若渴
    posted on 2010-07-16 00:15 imxylz 閱讀(16575) 評(píng)論(2)  編輯  收藏 所屬分類: Java Concurrency

    評(píng)論

    # re: 深入淺出 Java Concurrency (15): 鎖機(jī)制 part 10 鎖的一些其它問題 2010-07-16 08:56 yishh
    記得是在《Java Concurrency in Practice》這本書里面看到過jdk1.6以后synchronized的性能就有了巨大提高,按照書中給出的測(cè)試數(shù)據(jù)。和使用ReentrantLock 相差不多了了  回復(fù)  更多評(píng)論
      

    # re: 深入淺出 Java Concurrency (15): 鎖機(jī)制 part 10 鎖的一些其它問題 2010-07-16 10:31 xylz
    @yishh
    很有道理,如果不使用高級(jí)鎖的一些其它特性,比如條件變量,掛起等等特性,其實(shí)可以直接使用synchronized。  回復(fù)  更多評(píng)論
      


    ©2009-2014 IMXYLZ
    主站蜘蛛池模板: 亚洲一区二区三区在线观看蜜桃| 666精品国产精品亚洲| 亚洲中文字幕无码不卡电影| 亚洲日韩一页精品发布| 亚洲视频在线一区| 亚洲成_人网站图片| 黄页网址在线免费观看| 中文无码成人免费视频在线观看 | 亚洲av永久无码精品网址| 日韩在线视频线视频免费网站| 99久久婷婷免费国产综合精品| **aaaaa毛片免费| 日本高清免费不卡在线| 色噜噜亚洲精品中文字幕| 亚洲最新中文字幕| 国内成人精品亚洲日本语音| 国产一区二区三区免费观在线| 3d成人免费动漫在线观看| 国产成人精品免费直播| 亚洲AV无码久久精品色欲| 在线亚洲午夜片AV大片| 国产精品永久免费| 免费福利网站在线观看| 亚洲成AV人网址| 亚洲欧洲精品在线| 人妻仑乱A级毛片免费看| 91精品全国免费观看含羞草| 国产色爽女小说免费看| 亚洲国产精品久久久久婷婷老年| 亚洲欧美国产欧美色欲| 国产成人精品免费久久久久| 永久免费看bbb| 久久精品国产精品亚洲毛片| 精品视频免费在线| 亚洲视频免费观看| 亚洲乱码中文字幕手机在线| 91亚洲性爱在线视频| 成人妇女免费播放久久久| 毛色毛片免费观看| 亚洲AV无码精品无码麻豆| 在线观看国产一区亚洲bd|