激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

香港云服务器
服務器之家 - 編程語言 - Java教程 - Java的鎖機制:synchronized和CAS詳解

Java的鎖機制:synchronized和CAS詳解

2022-01-21 11:51我是坑貨 Java教程

這篇文章主要介紹了Java的鎖機制synchronized和CAS詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

提到Java的知識點一定會有多線程,JDK版本不斷的更迭很多新的概念和方法也都響應提出,但是多線程和線程安全一直是一個重要的關注點。比如說我們一入門就學習的synchronized怎么個實現和原理,還有總是被提到的CAS是啥,他和synchronized關系是啥?這里大概會讓你對這些東西有一個認識。

 

一 為什么要用鎖

我們使用多線程肯定是為了提高效率,壓榨硬件的性能提高效率,假設多一個線程相當于多一個人干活,但是有時候人多了就不是很好管理,可能出現問題。

比如我現在搞一個多線程的demo,我的本意是每個線程都高呼“ZPNB!”,我寫下了如下的代碼。

public class ThreadDemo implements Runnable{
  @Test
  public void testThread() {
      System.out.println("大聲告訴我:");
      ThreadDemo demo =  new ThreadDemo();
      Thread threadOne = new Thread(demo,"張三:ZPNB");
      Thread threadTwo = new Thread(demo,"李四:ZPNB");
      Thread threadThree = new Thread(demo,"王二麻子:ZPNB");
      Thread threadFour = new Thread(demo,"趙四:ZPNB");
      threadOne.start();
      threadTwo.start();
      threadThree.start();
      threadFour.start();
  }
  @Override
  public void run() {
//        synchronized (this){
          for( int i = 0; i < 10 ;i++  ){
              try {
                  System.out.println(Thread.currentThread().getName());
                  //這里設置0是因為Junit的限制你設置長了,他就執行一段時間就不執行了
                  Thread.sleep(0);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
//        }
  }

沒有加鎖的情況是這樣的,看起來很亂我希望他們每個人都喊十遍然后下一個人,顯然下面的結果不滿意

大聲告訴我:
李四:ZPNB
張三:ZPNB
李四:ZPNB
張三:ZPNB
李四:ZPNB
張三:ZPNB
張三:ZPNB
李四:ZPNB
張三:ZPNB
李四:ZPNB
張三:ZPNB
李四:ZPNB
張三:ZPNB
李四:ZPNB
張三:ZPNB
李四:ZPNB
張三:ZPNB
李四:ZPNB
張三:ZPNB
李四:ZPNB
王二麻子:ZPNB
趙四:ZPNB
王二麻子:ZPNB
趙四:ZPNB
王二麻子:ZPNB
趙四:ZPNB
趙四:ZPNB
趙四:ZPNB
王二麻子:ZPNB
王二麻子:ZPNB
趙四:ZPNB
王二麻子:ZPNB
趙四:ZPNB
王二麻子:ZPNB
趙四:ZPNB
王二麻子:ZPNB
趙四:ZPNB
王二麻子:ZPNB
趙四:ZPNB
王二麻子:ZPNB

但是如果我把synchronized的注釋取消就變成了我想要的依次每人喊十遍

大聲告訴我:
張三:ZPNB
張三:ZPNB
張三:ZPNB
張三:ZPNB
張三:ZPNB
張三:ZPNB
張三:ZPNB
張三:ZPNB
張三:ZPNB
張三:ZPNB
趙四:ZPNB
趙四:ZPNB
趙四:ZPNB
趙四:ZPNB
趙四:ZPNB
趙四:ZPNB
趙四:ZPNB
趙四:ZPNB
趙四:ZPNB
趙四:ZPNB
王二麻子:ZPNB
王二麻子:ZPNB
王二麻子:ZPNB
王二麻子:ZPNB
王二麻子:ZPNB
王二麻子:ZPNB
王二麻子:ZPNB
王二麻子:ZPNB
王二麻子:ZPNB
王二麻子:ZPNB
李四:ZPNB
李四:ZPNB
李四:ZPNB
李四:ZPNB
李四:ZPNB
李四:ZPNB
李四:ZPNB
李四:ZPNB
李四:ZPNB
李四:ZPNB

這就突出了鎖的重要性,我們希望有些線程能按照我們希望的一個順序依次來執行,而不是先到先得的。

 

二 synchronized怎么實現的

實際上每一個對象實際都擁有一個叫做監視器monitor的東西,線程只有獲得了這個監視器才能才能進入同步塊和同步方法,如果沒有獲取到監視器的線程將會被阻塞在同步塊和同步方法的入口處,具體過程如下圖:

Java的鎖機制:synchronized和CAS詳解

那如果沒獲取到監視器怎么辦,有個同步隊列的東西,你沒得到監視器就等一等,等上一個獲取監視器的exit推出監視器你再根據隊列順序去再獲取,當然可能在這個再獲取的過程碰到一個“新來的”沒進隊列直接跟你搶,你還沒搶過,那你就還要重復之前的等待過程。

其實這里還涉及一個鎖的“happen before”的概念(“ A hapen-bfore B,那么 A 的結果對 B 是可見的”),就是上一個線程如果對某些值有改寫,后一個應該在這個基礎上改寫的原則,假設一個計算程序,值都改了,新的線程你還在拿原先的值再去計算是不對的,應該是在新的值上面再去做操作,這樣多線程協作才有實際意義。

以下是關于synchronized作用范圍(基本是實際對象或者是類對象,如果你是類對象的話,那你new多少個實例對象還是被鎖的。)

Java的鎖機制:synchronized和CAS詳解

 

三 CAS來者何人

CAS突然這個概念出來作為線程安全的一個實現方式出現,那它和synchronized是一個什么樣的關系呢?

實際二者應該是同級的概念,大家都是鎖,synchronized是悲觀鎖,基本就是來一個線程就是鎖起來,阻塞同步的。認為任何操作都有可能是沖突,所以按照最壞的情況來處理,線程競爭阻塞了就阻塞,阻塞結束了就喚醒阻塞的進程。

CAS就是compare and swap ,不是直接鎖起來,大概意思就是:
CAS(V,O,N),包含三個值分別為:V 內存地址存放的實際值;O 預期的值(舊值);N 更新的新值。當V和O相同時,也就是說舊值和內存中實際的值相同表明該值沒有被其他線程更改過,即該舊值O就是目前來說最新的值了,自然而然可以將新值N賦值給V。反之,V和O不相同,表明該值已經被其他線程改過了則該舊值O不是最新版本的值了,所以不能將新值N賦給V,返回V即可。當多個線程使用CAS操作一個變量是,只有一個線程會成功,并成功更新,其余會失敗。失敗的線程會重新嘗試,當然也可以選擇掛起線程

CAS對于線程競爭沖突的情況相對來說就溫柔一些,他會有自己的重試機制,就是這次不行我等一會再去看看,而不是直接阻塞掛起再喚醒的狀態,這樣太耗費時間了。

在Java.util,ConCurrent包里面很多都是用CAS來處理同步的問題,而不是直接來個synchronized來修飾。

 

四synchronized和CAS孰優孰劣

實際上現在來看,還真不好說,因為在CAS的方案提出,實際上synchronized也是不斷的進步的。不能說CAS一定比synchronized好。

比如說CAS也會有自己的問題,最主要的有:ABA,自旋時間過長和只能保證一個共享變量的原子操作,雖然說都要相關的解決方案:

(1)ABA就是兩個線程第一個線程將最開始的A值改成B再改成A,第二個線程接手直接CAS,會得不到之前的轉換的過程,解決方式跟數據庫一樣加一個版本號1A 2B 3C解決。

(2)自旋時間過長就是線程競爭沖突,不停地重試,實際是一個循環操作,這個循環可能要等好長時間,導致所謂的自旋時間過長。

(3)只能操作一個共享原子,就讓這個原子變成一個對象,把要共享的都塞進去。

synchronized自身也在不斷地優化自身,甚至也借鑒了CAS的思想在1.6里面。為了減少獲得鎖和釋放鎖帶來的性能消耗,引入了“偏向鎖”和“輕量級鎖”,在Java SE 1.6中,鎖一共有4種狀態,級別從低到高依次是:無鎖狀態、偏向鎖狀態、輕量級鎖狀態和重量級鎖狀態。

偏向鎖(通過線程ID來看對象頭和棧幀里面查找線程ID(記錄的線程ID就是偏向的線程ID),有就獲取沒有就嘗試CAS設置自己為偏向的線程)

具體如下:

當一個線程訪問同步塊并獲取鎖時,會在對象頭和棧幀中的鎖記錄里存儲鎖偏向的線程ID,以后該線程在進入和退出同步塊時不需要進行CAS操作來加鎖和解鎖,只需簡單地測試一下對象頭的Mark Word里是否存儲著指向當前線程的偏向鎖。如果測試成功,表示線程已經獲得了鎖。如果測試失敗,則需要再測試一下Mark Word中偏向鎖的標識是否設置成1(表示當前是偏向鎖),如果沒有設置,則使用CAS競爭鎖;如果設置了,則嘗試使用CAS將對象頭的偏向鎖指向當前線程。

輕量級鎖

(替換鎖的指針替換成就獲得鎖,替換不成就自旋循環去找機會替換)

具體如下:

線程在執行同步塊之前,JVM會先在當前線程的棧楨中創建用于存儲鎖記錄的空間,并將對象頭中的Mark Word復制到鎖記錄中。然后線程嘗試使用CAS將對象頭中的Mark Word替換為指向鎖記錄的指針。如果成功,當前線程獲得鎖,如果失敗,表示其他線程競爭鎖,當前線程便嘗試使用自旋來獲取鎖。

重量級鎖

(monitor監視器鎖的實現,最重的一步,因為涉及到用戶態和系統態切換。)

重量級鎖是依賴對象內部的monitor鎖來實現。當系統檢查到鎖是重量級鎖之后,會把等待想要獲得鎖的線程進行阻塞,被阻塞的線程不會消耗cup。但是阻塞或者喚醒一個線程時,都需要操作系統來幫忙,需要從用戶態轉換到內核態,而轉換狀態是需要消耗很多時間。

這么看來synchronized并不是那么不堪,未必你用CAS實現的就一定在某些環境比synchronized這個“元老”強。

 

總結

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注服務器之家的更多內容!

原文鏈接:https://blog.csdn.net/FeiChangWuRao/article/details/120489390

延伸 · 閱讀

精彩推薦
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
887
主站蜘蛛池模板: 精品国产96亚洲一区二区三区 | 日日草夜夜 | 黄色免费不卡视频 | 18被视频免费观看视频 | 日本a∨精品中文字幕在线 国产精品片www48888 | 亚洲精品aa | 欧美日韩在线视频一区 | 国产亚洲黑人性受xxxx精品 | 免费看成人av | 91一级毛片 | 一本一本久久a久久精品综合小说 | 国产无区一区二区三麻豆 | 国产成人在线观看免费网站 | av一二三四区| 一级黄色国产视频 | 国产免费久久久 | 亚洲日色| 19禁国产精品福利视频 | 成人一级免费视频 | 国产精品刺激对白麻豆99 | 天天看成人免费毛片视频 | avav在线播放 | 午夜视频免费播放 | 久久电影一区二区 | 长泽雅美av | 欧美一级高潮片免费的 | 91精品久久香蕉国产线看观看 | 毛片一区二区三区四区 | 国产一区国产二区在线观看 | 福利免费视频 | 国产高清片| 日本免费一区二区三区四区 | 欧美一级黄色影院 | 毛片福利| 欧美一级全黄 | 亚洲啊v在线观看 | 日韩欧美视频一区二区三区 | 日本视频网| 欧美精品免费一区二区三区 | 国产毛片自拍 | 欧美日韩在线免费观看 |