【高并發(fā)】2追他、多線程中的鎖

一、多線程中的鎖

在多線程中岛蚤,鎖就是要實現(xiàn)線程對資源的訪問控制邑狸。從程序的角度來看,鎖就是一個對象涤妒,這個對象需要完成以下幾個事情

  • 記錄該對象是否被某個線程占用单雾;
  • 如果被某個線程占用,還需記錄這個線程的 Thread ID;
  • 記錄其他阻塞硅堆、等待拿到這個鎖的線程的集合屿储,在當(dāng)前線程釋放鎖后,從該集合中取出一個線程喚醒渐逃;

1.1 鎖的分類

樂觀鎖 和 悲觀鎖

樂觀鎖顧名思義就是一種樂觀的思想,即每次拿取數(shù)據(jù)時認(rèn)為其他線程不會修改疯潭,所以不會上鎖面殖,但是在更新時會判斷在此期間有沒有其他線程更新該數(shù)據(jù)畜普,采取在寫入時先讀取當(dāng)前版本號進(jìn)行比較,如果版本號相同钝荡,則更新舶衬,如果不同,則重復(fù)讀取-比較-寫的操作端辱。

樂觀鎖適用于多讀的應(yīng)用類型舞蔽,這樣可以提高吞吐率码撰。Java 中的樂觀鎖基本上都是通過 CAS(Compare And Swap 比較并交換)實現(xiàn)。

悲觀鎖顧名思義就是一種悲觀的思想朵栖,即每次拿取數(shù)據(jù)時都會認(rèn)其他線程會修改陨溅,所以在每次讀取數(shù)據(jù)時都會上鎖绍在,這樣其他線程想要讀取該數(shù)據(jù)時就會 block雹有,直到拿到鎖件舵。

悲觀鎖適用于多寫的應(yīng)用類型铅祸,Java 中 synchronized 關(guān)鍵字的實現(xiàn)就是悲觀鎖合武,AQS 包下的鎖則是先嘗試樂觀鎖去獲取鎖,獲取不到盟庞,才會轉(zhuǎn)換為悲觀鎖什猖,如 RetreenLock红淡。

共享鎖 和 排它鎖

排它鎖又稱為獨占鎖、獨享鎖,Java 中大部分的鎖都是排它鎖桶蝎。

共享鎖又被稱為讀鎖登渣,獲得共享鎖后,可以查看但是不能修改和刪除數(shù)據(jù)胜茧,其他線程此時也可以獲取到共享鎖竹揍,也可以查看但是不能修改和刪除數(shù)據(jù)芬位。

Java 中共享鎖和排它鎖的典型是讀寫鎖 ReentrantReadWriteLock带到,其中讀鎖是共享鎖,寫鎖是獨享鎖被饿,兩個鎖不會同時出現(xiàn),即要么有一個或多個線程同時持有讀鎖闪金,要么只有一個線程持有寫鎖论颅。

公平鎖 和 非公平鎖

公平鎖是指按照線程請求順序來分配鎖。

非公平是指多個線程獲取鎖的順序并不是按照申請鎖的順序漏设,有可能后申請的線程優(yōu)先于先申請的線程獲得鎖郑口,也有可能造成優(yōu)先級反轉(zhuǎn)或線程饑餓(即每次釋放就會被插隊搶鎖盾鳞,從而導(dǎo)致某個線程在很長一段時間搶不到鎖,始終無法執(zhí)行)雁仲。

Java 中默認(rèn)的都是非公平鎖,在線程啟動后會嘗試插隊去搶鎖攒砖,如果沒有搶到吹艇,則再排隊。這樣的設(shè)計主要是為了 提高效率受神,避免線程喚醒時帶來的空檔期鼻听。

自旋鎖

自旋鎖是指嘗試獲取鎖的線程不會立即阻塞,而是采用循環(huán)的方式去嘗試獲取鎖撑教,這樣能有效的減少線程上下文切換的消耗醉拓,但是會消耗 CPU收苏。

如果該線程一直獲取不到鎖鹿霸,將導(dǎo)致一直占用 CPU 自旋懦鼠,因此需要設(shè)定自旋等待的最大時間。在 JDK 1.6 引入了適應(yīng)性自旋鎖葛闷,即自旋等待的最大時間由前一次在同一個鎖上的自旋時間以及鎖持有者的狀態(tài)來決定淑趾,通過 -XX:+UseSpinning 開啟扣泊,-XX:PreBlockSpin=n 設(shè)置自旋的次數(shù)嘶摊;在 JDK 1.7 后,去掉了該參數(shù)阱飘,由 JVM 控制虱颗。

可重入鎖

可重入鎖又叫遞歸鎖忘渔,是指同一個線程在外層方法獲得鎖的時候,在進(jìn)入其內(nèi)部方法會自動獲取該鎖畦粮。

Java 中 Synchronized 和 ReetrantLock 都是可重入鎖宣赔。可重入鎖可以有效避免死鎖問題吏祸。

死鎖

當(dāng)兩個(或更多)線程(或進(jìn)程)互相持有對方所需的資源,又不主動釋放犁罩,導(dǎo)致所有線程(或進(jìn)程)無法繼續(xù)執(zhí)行床估,導(dǎo)致程序陷入無盡的阻塞诱渤,這就是死鎖,如下圖所示:

死鎖
產(chǎn)生死鎖的條件:
  • 互斥條件:每個資源只能被一個線程(或進(jìn)程)使用,其他線程(或進(jìn)程)要使用該資源赡茸,需要等待該資源被釋放;
  • 請求與保持條件:一個線程因請求資源而阻塞時遗菠,則需要對已獲得的資源保持不放辙纬;
  • 不剝奪條件:線程已獲得的資源叭喜,在未使用完之前贺拣,不會被強(qiáng)行剝奪譬涡;
  • 循環(huán)等待條件:若干線程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系昂儒;
必然死鎖的代碼:
public static void main(String[] args) {

  Object A = new Object();
  Object B = new Object();
  
  new Thread(() -> {
      synchronized(A) {
        try {
            TimeUnit.SECONDS.sleep(1);
            synchronized (B) {
                System.out.println(Thread.currentThread().getName() + "獲取到了兩把鎖");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
      }
  }, "A").start();
  
  new Thread(() -> {
      synchronized(B) {
        try {
            TimeUnit.SECONDS.sleep(1);
            synchronized (A) {
                System.out.println(Thread.currentThread().getName() + "獲取到了兩把鎖");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
      }
  }, "B").start();
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末渊跋,一起剝皮案震驚了整個濱河市着倾,隨后出現(xiàn)的幾起案子卡者,更是在濱河造成了極大的恐慌,老刑警劉巖崇决,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異建邓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)官边,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跳仿,“玉大人,你說我怎么就攤上這事塔嬉〗骶浚” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鸯屿。 經(jīng)常有香客問我寄摆,道長,這世上最難降的妖魔是什么桑阶? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任勾邦,我火速辦了婚禮蚣录,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘眷篇。我一直安慰自己萎河,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著虐杯,像睡著了一般玛歌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上擎椰,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天沾鳄,我揣著相機(jī)與錄音,去河邊找鬼确憨。 笑死,一個胖子當(dāng)著我的面吹牛瓤的,可吹牛的內(nèi)容都是我干的休弃。 我是一名探鬼主播塔猾,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼睦擂,長吁一口氣:“原來是場噩夢啊……” “哼顿仇!你這毒婦竟也來了囤采?” 一聲冷哼從身側(cè)響起乓搬,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤坷澡,失蹤者是張志新(化名)和其女友劉穎项郊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體任洞,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡盅弛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年讨盒,在試婚紗的時候發(fā)現(xiàn)自己被綠了勺择。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稿辙。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡旧噪,死狀恐怖宦赠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤丐谋,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布践美,位于F島的核電站敛滋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜咱揍,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧遍愿,春花似錦桅咆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背婉称。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人兴猩。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像衅码,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容