<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      簡直了,被“Java并發(fā)鎖”問題追問到自閉...

      故事

      地鐵上,小帥雙目空洞地望著窗外...絕望,發(fā)自內(nèi)心地感到絕望...

      距離失業(yè)已經(jīng)過去兩個月了,這是小帥接到的第四次面試邀請。“回去等通知吧...”,簡簡單單的六個字,把小帥的心再次打入了冰窖。

      上次“【ThreadLocal問出花】”,小帥其實也有吸取教訓得,這次對于多線程的問題還是做了很多準備的...可是沒想到這次的結果居然也還是這樣。

      “Java中的鎖了解吧?介紹一下吧”,面試官不緊不慢地問到。

      “樂觀鎖、悲觀鎖、公平鎖、非公平鎖,然后平時咱們的synchronized是基于.....”小帥把知道的所有關于鎖的基本都回答了一遍。

      面試官對他笑了笑,“就這些嗎?還有呢?比如自旋鎖、可重入鎖、獨占鎖....并且說一下你的理解,或者聊一下使用場景的優(yōu)劣吧。”

      “額.....以前好像看到過...”小帥語無倫次地回答到。

      “嗯,行吧,之前的那些答得可以的,不過一會我這邊有個會,要不今天咱們就聊到這里?回去等通知吧...”

      Java中讓人眼花繚亂的鎖你是否真的一一清楚了?

      試問這樣一個大而寬的問題,大家能夠總結全嗎,如果讓各位來回答,能否回答完全呢?

      我們在實際的并發(fā)編程中,常常遇到多個線程訪問一個共享變量的情況,當同時對共享變量進行讀寫操作的時候,就會產(chǎn)生數(shù)據(jù)不一致的情況。為了保證資源獲取的有序性,我們就常常會用到并發(fā)鎖。

      那么接下來咱們就來聊聊這些Java并發(fā)鎖的理解吧。我們將從以下這些方面來一起回顧一下Java中的并發(fā)鎖。

      概要

      樂觀鎖和悲觀鎖:線程是否鎖住同步資源

      大家其實對樂觀鎖和悲觀鎖聽說的比較多一些,所以咱們就先來聊聊這兩種類型的鎖。這兩種類型的鎖,本質(zhì)區(qū)分是要看線程是否鎖住同步資源。

      先來看一下悲觀鎖。悲觀鎖就是每次去拿數(shù)據(jù)的時候都會認為別人會修改數(shù)據(jù),所以在讀取數(shù)據(jù)的時候都會上鎖。這樣就會導致線程臨時阻塞。

      悲觀鎖

      再來看一下樂觀鎖,樂觀鎖就是每次在拿數(shù)據(jù)的時候都假設別人不會修改數(shù)據(jù),所以都不會進行上鎖;只有在更新數(shù)據(jù)的時候才去判斷之前有沒有別的線程更新了這條數(shù)據(jù)。如果沒有更新,那么當前線程會自己修改數(shù)據(jù)并且寫入成功。如果數(shù)據(jù)已經(jīng)被其他線程更新了,那么會報錯或者自動重試,例如下圖。

      樂觀鎖

      上述兩種鎖,并沒有優(yōu)劣之分。只是看相關的場景然后分別去使用。

      樂觀鎖:適用于寫少讀多的場景。因為不用上鎖,釋放鎖,省去了鎖的開銷,從而提升了吞吐量。

      悲觀鎖:適用于寫多讀少的場景。因為線程競爭激烈,如果使用樂觀鎖會導致線程不斷進行重試,反而降低吞吐量。

      共享鎖和獨占鎖:多個線程是否共享同一把鎖

      并發(fā)場景下,如果多個線程能夠共享一把鎖,那么就是所謂的共享鎖,如果不能,那么則為獨占鎖(其他命名:排他鎖或者獨享鎖)。

      共享鎖指鎖可以被多個線程持有。如果一個線程對數(shù)據(jù)加上共享鎖,那么其他線程只能對數(shù)據(jù)再加共享鎖,不能加獨占鎖。另外的共享鎖的線程只能讀數(shù)據(jù),不能修改數(shù)據(jù)。如下圖。

      共享鎖

      獨占鎖是指鎖一次只能被一個線程持有,如果一個線程對數(shù)據(jù)加上獨占鎖,那么其他的線程則不能對該數(shù)據(jù)再加任何類型的鎖。如果一個線程獲取獨占鎖,那么則該線程既可以讀數(shù)據(jù)又可以修改數(shù)據(jù)。

      獨占鎖

      對于獨占鎖來說,大家比較熟悉的就是synchronized和J.U.C包中的Lock實現(xiàn)類。

      大家可能也聽說過互斥鎖,其實互斥鎖就是獨占鎖的一種常規(guī)實現(xiàn)。

      讀寫鎖是共享鎖的一種具體實現(xiàn)。讀寫鎖管理一組鎖,一個是只讀的鎖,一個是寫鎖。

      讀鎖可以再沒有寫鎖的時候被多個線程同時持有,而寫鎖是獨占的,于此同時寫鎖的優(yōu)先級要高于讀鎖,一個獲得了讀鎖的線程必須能看到前一個釋放的寫鎖更新的內(nèi)容。

      讀寫鎖和互斥鎖對比,其性能更高,每次只有一個寫線程,但是有多個線程可以并發(fā)讀。

      讀寫鎖

      例如,ReentrantReadWriteLock。具體偽代碼如下:

      import java.util.concurrent.locks.ReentrantReadWriteLock;
      /**
       * 公眾號:程序員老貓
       **/
      public class ReadWriteLockDemo {
      
          private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
      
          public void readData() {
              lock.readLock().lock(); // 獲取讀鎖
              try {
                  // 讀取共享數(shù)據(jù)
              } finally {
                  lock.readLock().unlock(); // 釋放讀鎖
              }
          }
      
          public void writeData() {
              lock.writeLock().lock(); // 獲取寫鎖
              try {
                 // 修改或寫入數(shù)據(jù)
              } finally {
                  lock.writeLock().unlock(); // 釋放寫鎖
              }
          }
      }
      
      

      公平鎖和非公平鎖:多線程競爭時是否要排隊

      我們根據(jù)多線程在競爭鎖的時候是否需要排隊從來判斷其鎖的類型是公平鎖還是非公平鎖。

      公平鎖指多個線程按照申請鎖的順序來獲取鎖。類似食堂排隊打飯,先到的可以先打飯。

      公平鎖

      非公平鎖是指多個線程獲取鎖的順序并不是按照申請鎖的順序進行的,有可能后申請的比先申請的優(yōu)先獲得鎖,高并發(fā)場景下,優(yōu)先級就有可能發(fā)生反轉。如下圖:

      非公平鎖

      咱們在日常開發(fā)的過程中經(jīng)常用到synchronized,其底層其實就是非公平鎖。當然如果我們要使用公平鎖的情況下,我們也可以使用ReentrantLock。
      偽代碼如下:

      Lock lock = new ReetrantLock(false);
      

      ReentrantLock默認為非公平鎖,設置為true的時候表示公平鎖。當設置為false的時候表示非公平鎖。

      可重入鎖和不可重入鎖:同一個線程中多個流程是否能夠獲取同一把鎖。

      如果一個線程中的多個流程能夠獲取同一把鎖,那么我們就叫該所為可重入鎖,反之則為不可重入鎖。咱們光看文字描述的話可能比較抽象。我們看一下下圖。
      可重入鎖

      在Java中可重入鎖一般有ReentrantLock,其命名就已經(jīng)很明確了。另外的synchronized也是可重入鎖。
      可重入鎖的優(yōu)勢是可以一定程度上避免死鎖發(fā)生。上面的示意圖轉換為如下demo:

      public synchronized void methodA() {
        methodB()
      }
      
      public synchronized void methodB() {
        methodC()
      }
      
      public synchronized void methodC(){
        doSomeThing()
      }
      

      自旋鎖或者自適應自旋鎖:線程鎖定同步資源失敗,如該線程沒有被阻塞場景下發(fā)生

      如果一個線程鎖住同步資源失敗,但是又希望這個線程不被阻塞,那么此時咱們就可以使用自旋鎖或者自適應自旋鎖。
      自旋鎖指線程沒有獲得鎖的情況下不被掛起,而是執(zhí)行一個忙循環(huán)。那么這個忙循環(huán)的話就成為自旋。如下:

      自旋鎖

      目的:減少線程被掛起的概率,因為線程被掛起和喚醒也是消費資源。

      Java中AtomicInteger類就有自旋的操作,如下源代碼:

      @HotSpotIntrinsicCandidate
          public final int getAndAddInt(Object o, long offset, int delta) {
              int v;
              do {
                  v = getIntVolatile(o, offset);
              } while (!weakCompareAndSetInt(o, offset, v, v + delta));
              return v;
          }
      

      上述方法中weakCompareAndSetInt(),就可以被稱為是CAS操作,如果失敗,那么會一直循環(huán)獲取當前的value值然后進行重試操作。那么這個過程其實就是自旋了。

      其他分類的鎖。

      上述我們聊到的這系列的鎖應該是大家聽到比較多的。其實還有其他的分類。在此不做一一展開了,有興趣的小伙伴當然也可以深入去了解一下。
      例如根據(jù)線程競爭同步資源的時候,細節(jié)流程是否發(fā)生變化,分為偏向鎖、輕量級鎖和重量級鎖。
      在比如,相信大家對HashMap底層原理倒背如流吧,對ConcurrentHashMap應該也有了解,那么ConcurrentHashMap底層其實將鎖的粒度進一步細化了,存在了分段鎖的概念等等。

      總結

      這些讓人眼花繚亂的鎖,如果面試官問到的話,大家是否能夠說出一二呢?相信看完上面的解釋,大家心里多多少少也有數(shù)了吧。當然關于最后一點其他分類的鎖,老貓沒有展開。有興趣的小伙伴可以自行查閱一下這些分類。

      posted @ 2024-04-02 22:28  程序員老貓  閱讀(639)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 在线免费播放av观看| 国产一区二区三区自拍视频| 亚洲精品久久久久国产| 国内综合精品午夜久久资源| 国产精品不卡一二三区| 国产精品免费看久久久| 麻豆国产成人AV在线播放| 亚洲欧美日韩尤物AⅤ一区| 色翁荡息又大又硬又粗又视频图片| 狠狠躁夜夜躁人人爽天天5| 久久精品熟女亚洲av麻| 在线中文字幕国产精品| 人妻少妇偷人无码视频| 亚洲av专区一区| 国产精品视频午夜福利| 国产亚洲人成网站在线观看| 久久九九兔免费精品6| 精品一区二区三区四区激情| 日韩有码中文字幕av| 亚洲欧洲日产国码AV天堂偷窥 | 最新亚洲人成网站在线影院| 亚洲精品三区四区成人少| 8AV国产精品爽爽ⅤA在线观看| 久久香蕉国产线看观看猫咪av| 强奷乱码中文字幕| 亚洲综合小综合中文字幕| 精品国产中文字幕av| 国产超碰无码最新上传| 中文字幕亚洲国产精品| 国产一区二区三区我不卡| 边摸边吃奶边做爽动态| 国产精品午夜福利精品| 亚洲AV乱码毛片在线播放| 国产一区在线播放av| 宁南县| 色吊丝二区三区中文写幕| 中文字幕午夜福利片午夜福利片97 | 国产成人精品一区二区三| 性色av无码久久一区二区三区| 国模在线视频一区二区三区| 亚洲精品一区二区动漫|