国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

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

服務(wù)器之家 - 編程語言 - Java教程 - 淺談Java并發(fā)之同步器設(shè)計(jì)

淺談Java并發(fā)之同步器設(shè)計(jì)

2022-02-25 00:29onlythinking Java教程

這篇文章主要介紹Java并發(fā)之同步器設(shè)計(jì),本文以記錄方式并發(fā)編程中同步器設(shè)計(jì)的一些共性特征。并簡單介紹了Java中的AQS,需要的朋友可以參考一下文章的詳細(xì)內(nèi)容

前言:

Java并發(fā)內(nèi)存模型詳情了解到多進(jìn)程(線程)讀取共享資源的時(shí)候存在競爭條件。

淺談Java并發(fā)之同步器設(shè)計(jì)

計(jì)算機(jī)中通過設(shè)計(jì)同步器來協(xié)調(diào)進(jìn)程(線程)之間執(zhí)行順序。同步器作用就像登機(jī)安檢人員一樣可以協(xié)調(diào)旅客按順序通過。

在Java中,同步器可以理解為一個(gè)對象,它根據(jù)自身狀態(tài)協(xié)調(diào)線程的執(zhí)行順序。比如鎖(Lock),信號(hào)量(Semaphore),屏障(CyclicBarrier),阻塞隊(duì)列(Blocking Queue)。

這些同步器在功能設(shè)計(jì)上有所不同,但是內(nèi)部實(shí)現(xiàn)上有共通的地方。

 

1、同步器

同步器的設(shè)計(jì)一般包含幾個(gè)方面:狀態(tài)變量設(shè)計(jì)(同步器內(nèi)部狀態(tài)),訪問條件設(shè)定,狀態(tài)更新,等待方式,通知策略。

淺談Java并發(fā)之同步器設(shè)計(jì)

訪問條件是控制線程是否能執(zhí)行(訪問共享對象)的條件,它往往與狀態(tài)變量緊密相關(guān)。而通知策略是線程釋放鎖定狀態(tài)后通知其它等待線程的方式,一般有以下幾種情況:

  • 通知所有等待的線程。
  • 通知1個(gè)隨機(jī)的N個(gè)等待線程。
  • 通知1個(gè)特定的N個(gè)等待線程

看下面例子,通過鎖方式的同步器

public class Lock{
// 狀態(tài)變量 isLocked
private boolean isLocked = false; 
public synchronized void lock() throws InterruptedException{
  // 訪問條件 當(dāng)isLocked=false 時(shí)獲得訪問權(quán)限否則等待
  while(isLocked){
    // 阻塞等待
    wait();
  }
  //狀態(tài)更新 線程獲得訪問權(quán)限
  isLocked = true;
}

public synchronized void unlock(){
  //狀態(tài)更新 線程釋放訪問權(quán)限
  isLocked = false;
  // 通知策略 object.notify | object.notifyAll
  notify(); 
}
}

我們用計(jì)數(shù)信號(hào)量控制同時(shí)執(zhí)行操作活動(dòng)數(shù)。這里模擬一個(gè)連接池。

public class PoolSemaphore {
 // 狀態(tài)變量 actives 計(jì)數(shù)器
  private int actives = 0;
  private int max;
  public PoolSemaphore(int max) {
      this.max = max;
  }
  public synchronized void acquire() throws InterruptedException {
      //訪問條件 激活數(shù)小于最大限制時(shí),獲得訪問權(quán)限否則等待
      while (this.actives == max) wait();
      //狀態(tài)更新 線程獲得訪問權(quán)限
      this.actives++;
      // 通知策略 object.notify | object.notifyAll
      this.notify();
  }
  public synchronized void release() throws InterruptedException {
      //訪問條件 激活數(shù)不為0時(shí),獲得訪問權(quán)限否則等待
      while (this.actives == 0) wait();
       //狀態(tài)更新 線程獲得訪問權(quán)限
      this.actives--;
      // 通知策略 object.notify | object.notifyAll
      this.notify();
  }
}

1.1 原子指令

同步器設(shè)計(jì)里面,最重要的操作邏輯是“如果滿足條件,以更新狀態(tài)變量來標(biāo)志線程獲得或釋放訪問權(quán)限”,該操作應(yīng)具備原子性

比如test-and-set 計(jì)算機(jī)原子指令,意思是進(jìn)行條件判斷滿足則設(shè)置新值。

function Lock(boolean *lock) { 
  while (test_and_set(lock) == 1); 
}


另外還有很多原子指令 fetch-and-add compare-and-swap,注意這些指令需硬件支持才有效。

同步操作中,利用計(jì)算機(jī)原子指令,可以避開鎖,提升效率。java中沒有 test-and-set 的支持,不過 java.util.concurrent.atomic 給我們提供了很多原子類API,里面支持了 getAndSet 和compareAndSet 操作。

看下面例子,主要在區(qū)別是等待方式不一樣,上面是通過wait()阻塞等待,下面是無阻塞循環(huán)。

public class Lock{
// 狀態(tài)變量 isLocked
private AtomicBoolean isLocked = new AtomicBoolean(false);
public void lock() throws InterruptedException{
  // 等待方式 變?yōu)樽孕却?
  while(!isLocked.compareAndSet(false, true));
  //狀態(tài)更新 線程獲得訪問權(quán)限
  isLocked.set(true);
}

public synchronized void unlock(){
  //狀態(tài)更新 線程釋放訪問權(quán)限
  isLocked.set(false);
}
}

1.2 關(guān)于阻塞擴(kuò)展說明

阻塞意味著需要將進(jìn)程或線程狀態(tài)進(jìn)行轉(zhuǎn)存,以便還原后恢復(fù)執(zhí)行。這種操作是昂貴繁重,而線程基于進(jìn)程之上相對比較輕量。線程的阻塞在不同編程平臺(tái)實(shí)現(xiàn)方式也有所不同,像Java是基于JVM運(yùn)行,所以它由JVM完成實(shí)現(xiàn)。

在《Java Concurrency in Practice》中,作者提到

競爭性同步可能需要OS活動(dòng),這增加了成本。當(dāng)爭用鎖時(shí),未獲取鎖的線程必須阻塞。 JVM可以通過旋轉(zhuǎn)等待(反復(fù)嘗試獲取鎖直到成功)來實(shí)現(xiàn)阻塞,也可以通過操作系統(tǒng)掛起阻塞的線程來實(shí)現(xiàn)阻塞。哪種效率更高取決于上下文切換開銷與鎖定可用之前的時(shí)間之間的關(guān)系。對于短暫的等待,最好使用自旋等待;對于長時(shí)間的等待,最好使用暫停。一些JVM基于對過去等待時(shí)間的分析數(shù)據(jù)來自適應(yīng)地在這兩者之間進(jìn)行選擇,但是大多數(shù)JVM只是掛起線程等待鎖定。

從上面可以看出JVM實(shí)現(xiàn)阻塞兩種方式

  • 旋轉(zhuǎn)等待(spin-waiting),簡單理解是不暫停執(zhí)行以循環(huán)的方式等待,適合短時(shí)間場景。
  • 通過操作系統(tǒng)掛起線程。

JVM中通過 -XX: +UseSpinning 開啟旋轉(zhuǎn)等待, -XX: PreBlockSpi =10指定最大旋轉(zhuǎn)次數(shù)。

淺談Java并發(fā)之同步器設(shè)計(jì)

 

2、AQS

AQS是AbstractQueuedSynchronizer簡稱。本節(jié)對AQS只做簡單闡述,并不全面。

java.util.concurrent包中的 ReentrantLock,CountDownLatch,Semaphore,CyclicBarrier等都是基于是AQS同步器實(shí)現(xiàn)。

狀態(tài)變量 是用 int state 來表示,狀態(tài)的獲取與更新通過以下API操作。

int getState()
void setState(int newState)
boolean compareAndSetState(int expect, int update)


該狀態(tài)值在不同API中有不同表示意義。比如ReentrantLock中表示持有鎖的線程獲取鎖的次數(shù),Semaphore表示剩余許可數(shù)。

關(guān)于等待方式和通知策略的設(shè)計(jì)

AQS通過維護(hù)一個(gè)FIFO同步隊(duì)列(Sync queue)來進(jìn)行同步管理。當(dāng)多線程爭用共享資源時(shí)被阻塞入隊(duì)。而線程阻塞與喚醒是通過 LockSupport.park/unpark API實(shí)現(xiàn)。

它定義了兩種資源共享方式。

  • Exclusive(獨(dú)占,只有一個(gè)線程能執(zhí)行,如ReentrantLock)
  • Share(共享,多個(gè)線程可同時(shí)執(zhí)行,如Semaphore/CountDownLatch)

每個(gè)節(jié)點(diǎn)包含waitStatus(節(jié)點(diǎn)狀態(tài)),prev(前繼),next(后繼),thread(入隊(duì)時(shí)線程),nextWaiter(condition隊(duì)列的后繼節(jié)點(diǎn))

淺談Java并發(fā)之同步器設(shè)計(jì)

waitStatus 有以下取值

  • CANCELLED(1) 表示線程已取消。當(dāng)發(fā)生超時(shí)或中斷,節(jié)點(diǎn)狀態(tài)變?yōu)槿∠鬆顟B(tài)不再改變。
  • SIGNAL(-1) 表示后繼節(jié)點(diǎn)等待前繼的喚醒。后繼節(jié)點(diǎn)入隊(duì)時(shí),會(huì)將前繼狀態(tài)更新為SIGNAL。
  • CONDITION(-2) 表示線程在Condition queue 里面等待。當(dāng)其他線程調(diào)用了Condition.signal()方法后,CONDITION狀態(tài)的節(jié)點(diǎn)將從 Condition queue 轉(zhuǎn)移到 Sync queue,等待獲取鎖。
  • PROPAGATE(-3) 在共享模式下,當(dāng)前節(jié)點(diǎn)釋放后,確保有效通知后繼節(jié)點(diǎn)。
  • (0) 節(jié)點(diǎn)加入隊(duì)列時(shí)的默認(rèn)狀態(tài)。

AQS 幾個(gè)關(guān)鍵 API

  • tryAcquire(int) 獨(dú)占方式下,嘗試去獲取資源。成功返回true,否則false。
  • tryRelease(int) 獨(dú)占方式下,嘗試釋放資源,成功返回true,否則false。
  • tryAcquireShared(int) 共享方式下,嘗試獲取資源。返回負(fù)數(shù)為失敗,零和正數(shù)為成功并表示剩余資源。
  • tryReleaseShared(int) 共享方式下,嘗試釋放資源,如果釋放后允許喚醒后續(xù)等待節(jié)點(diǎn)返回true,否則false。
  • isHeldExclusively() 判斷線程是否正在獨(dú)占資源。

2.1 acquire(int arg)

public final void acquire(int arg) {
  if (
    // 嘗試直接去獲取資源,如果成功則直接返回
    !tryAcquire(arg)
      &&
      //線程阻塞在同步隊(duì)列等待獲取資源。等待過程中被中斷,則返回true,否則false
      acquireQueued(
        // 標(biāo)記該線程為獨(dú)占方式,并加入同步隊(duì)列尾部。
        addWaiter(Node.EXCLUSIVE), arg) 
     )
      selfInterrupt();
}

2.2 release(int arg)

public final boolean release(int arg) {
 // 嘗試釋放資源
  if (tryRelease(arg)) {
      Node h = head;
      if (h != null && h.waitStatus != 0)
        // 喚醒下一個(gè)線程(后繼節(jié)點(diǎn))
        unparkSuccessor(h);
      return true;
  }
  return false;
}
private void unparkSuccessor(Node node) {
....
   Node s = node.next; // 找到后繼節(jié)點(diǎn)
      if (s == null || s.waitStatus > 0) {//無后繼或節(jié)點(diǎn)已取消
          s = null;
         // 找到有效的等待節(jié)點(diǎn) 
          for (Node t = tail; t != null && t != node; t = t.prev)
              if (t.waitStatus <= 0)
                  s = t;
      }
      if (s != null)
          LockSupport.unpark(s.thread); // 喚醒線程
  }

總結(jié):

文章記錄并發(fā)編程中同步器設(shè)計(jì)的一些共性特征。并簡單介紹了Java中的AQS。

到此這篇關(guān)于淺談Java并發(fā)之同步器設(shè)計(jì)的文章就介紹到這了,更多相關(guān)Java并發(fā)之同步器設(shè)計(jì)內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://www.onlythinking.com/2020/06/09/java%E5%B9%B6%E5%8F%91%E4%B9%8Bsynchronizer%E8%A7%A3%E6%9E%90/

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 中文字幕成人 | 欧美中文字幕一区二区 | 夜夜嗨aⅴ免费视频 | 日韩精品一区二区三区 | 在线观看亚洲一区二区三区 | 啪啪伊人| 激情五月激情综合网 | 久久久亚洲国产天美传媒修理工 | 久久情趣视频 | 羞羞网站在线 | 欧美日韩激情 | 精品一区二区三区免费毛片 | 亚洲美女一区 | 久久精品成人 | 中文字幕一区二区三区在线视频 | 久久久久久久久久久亚洲 | 99热最新网站 | 伊人av成人 | 久久久久久久久久久久久国产 | 在线播放黄 | 日日麻批免费视频40分钟 | 成人午夜精品久久久久久久3d | 亚洲在线视频 | 精品av| av免费网站在线观看 | 成人亚洲一区二区 | 北条麻妃99精品青青久久 | 国产成人一级片 | 国产丝袜久久久 | 最近日韩中文字幕 | 国产精品极品美女在线观看免费 | 91精品国产欧美一区二区成人 | 国产视频久久 | 很黄很色很爽的视频 | 国产精品亚洲一区二区三区在线 | 色二区| 国产一区二区日韩 | 久久久精品日本 | 国产视频网 | 精品在线播放 | 成人av在线网站 |