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

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

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

服務(wù)器之家 - 編程語(yǔ)言 - JAVA教程 - Java并發(fā)系列之AbstractQueuedSynchronizer源碼分析(概要分析)

Java并發(fā)系列之AbstractQueuedSynchronizer源碼分析(概要分析)

2021-04-07 14:01勞夫子 JAVA教程

這篇文章主要為大家詳細(xì)介紹了Java并發(fā)系列之AbstractQueuedSynchronizer源碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

學(xué)習(xí)Java并發(fā)編程不得不去了解一下java.util.concurrent這個(gè)包,這個(gè)包下面有許多我們經(jīng)常用到的并發(fā)工具類,例如:ReentrantLock, CountDownLatch, CyclicBarrier, Semaphore等。而這些類的底層實(shí)現(xiàn)都依賴于AbstractQueuedSynchronizer這個(gè)類,由此可見這個(gè)類的重要性。所以在Java并發(fā)系列文章中我首先對(duì)AbstractQueuedSynchronizer這個(gè)類進(jìn)行分析,由于這個(gè)類比較重要,而且代碼比較長(zhǎng),為了盡可能分析的透徹一些,我決定用四篇文章對(duì)該類進(jìn)行一個(gè)比較完整的介紹。本篇文章作為概要介紹主要是讓讀者們對(duì)該類有個(gè)初步了解。為了敘述簡(jiǎn)單,后續(xù)有些地方會(huì)用AQS代表這個(gè)類。

1. AbstractQueuedSynchronizer這個(gè)類是干嘛的?

相信要許多讀者使用過(guò)ReentrantLock,但是卻不知道AbstractQueuedSynchronizer的存在。其實(shí)ReentrantLock實(shí)現(xiàn)了一個(gè)內(nèi)部類Sync,該內(nèi)部類繼承了AbstractQueuedSynchronizer,所有鎖機(jī)制的實(shí)現(xiàn)都是依賴于Sync內(nèi)部類,也可以說(shuō)ReentrantLock的實(shí)現(xiàn)就是依賴于AbstractQueuedSynchronizer類。于此類似,CountDownLatch, CyclicBarrier, Semaphore這些類也是采用同樣的方式來(lái)實(shí)現(xiàn)自己對(duì)于鎖的控制。可見,AbstractQueuedSynchronizer是這些類的基石。那么AQS內(nèi)部到底實(shí)現(xiàn)了什么以至于所以這些類都要依賴于它呢?可以這樣說(shuō),AQS為這些類提供了基礎(chǔ)設(shè)施,也就是提供了一個(gè)密碼鎖,這些類擁有了密碼鎖之后可以自己來(lái)設(shè)置密碼鎖的密碼。此外,AQS還提供了一個(gè)排隊(duì)區(qū),并且提供了一個(gè)線程訓(xùn)導(dǎo)員,我們知道線程就像一個(gè)原始的野蠻人,它不懂得講禮貌,它只會(huì)橫沖直撞,所以你得一步一步去教它,告訴它什么時(shí)候需要去排隊(duì)了,要到哪里去排隊(duì),排隊(duì)前要做些什么,排隊(duì)后要做些什么。這些教化工作全部都由AQS幫你完成了,從它這里教化出來(lái)的線程都變的非常文明懂禮貌,不再是原始的野蠻人,所以以后我們只需要和這些文明的線程打交道就行了,千萬(wàn)不要和原始線程有過(guò)多的接觸!

2. 為何說(shuō)AbstractQueuedSynchronizer提供了一把密碼鎖?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//同步隊(duì)列的頭結(jié)點(diǎn)
private transient volatile Node head;
 
//同步隊(duì)列的尾結(jié)點(diǎn)
private transient volatile Node tail;
 
//同步狀態(tài)
private volatile int state;
 
//獲取同步狀態(tài)
protected final int getState() {
 return state;
}
 
//設(shè)置同步狀態(tài)
protected final void setState(int newState) {
 state = newState;
}
 
//以CAS方式設(shè)置同步狀態(tài)
protected final boolean compareAndSetState(int expect, int update) {
 return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

上面的代碼列出了AQS的所有成員變量,可以看到AQS的成員變量只有三個(gè),分別是同步隊(duì)列頭結(jié)點(diǎn)引用,同步隊(duì)列尾結(jié)點(diǎn)引用以及同步狀態(tài)。注意,這三個(gè)成員變量都使用了volatile關(guān)鍵字進(jìn)行修飾,這就確保了多個(gè)線程對(duì)它的修改都是內(nèi)存可見的。整個(gè)類的核心就是這個(gè)同步狀態(tài),可以看到同步狀態(tài)其實(shí)就是一個(gè)int型的變量,大家可以把這個(gè)同步狀態(tài)看成一個(gè)密碼鎖,而且還是從房間里面鎖起來(lái)的密碼鎖,state具體的值就相當(dāng)于密碼控制著密碼鎖的開合。當(dāng)然這個(gè)鎖的密碼是多少就由各個(gè)子類來(lái)規(guī)定了,例如在ReentrantLock中,state等于0表示鎖是開的,state大于0表示鎖是鎖著的,而在Semaphore中,state大于0表示鎖是開的,state等于0表示鎖是鎖著的。

3. AbstractQueuedSynchronizer的排隊(duì)區(qū)是怎樣實(shí)現(xiàn)的?

Java并發(fā)系列之AbstractQueuedSynchronizer源碼分析(概要分析)

AbstractQueuedSynchronizer內(nèi)部其實(shí)有兩個(gè)排隊(duì)區(qū),一個(gè)是同步隊(duì)列,一個(gè)是條件隊(duì)列。從上圖可以看出,同步隊(duì)列只有一條,而條件隊(duì)列可以有多條。同步隊(duì)列的結(jié)點(diǎn)分別持有前后結(jié)點(diǎn)的引用,而條件隊(duì)列的結(jié)點(diǎn)只有一個(gè)指向后繼結(jié)點(diǎn)的引用。圖中T表示線程,每個(gè)結(jié)點(diǎn)包含一個(gè)線程,線程在獲取鎖失敗后首先進(jìn)入同步隊(duì)列排隊(duì),而想要進(jìn)入條件隊(duì)列該線程必須持有鎖才行。接下來(lái)我們看看隊(duì)列中每個(gè)結(jié)點(diǎn)的結(jié)構(gòu)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//同步隊(duì)列的結(jié)點(diǎn)
static final class Node {
 
 static final Node SHARED = new Node(); //表示當(dāng)前線程以共享模式持有鎖
 
 static final Node EXCLUSIVE = null; //表示當(dāng)前線程以獨(dú)占模式持有鎖
 
 static final int CANCELLED = 1//表示當(dāng)前結(jié)點(diǎn)已經(jīng)取消獲取鎖
 
 static final int SIGNAL = -1//表示后繼結(jié)點(diǎn)的線程需要運(yùn)行
 
 static final int CONDITION = -2//表示當(dāng)前結(jié)點(diǎn)在條件隊(duì)列中排隊(duì)
 
 static final int PROPAGATE = -3//表示后繼結(jié)點(diǎn)可以直接獲取鎖
 
 volatile int waitStatus; //表示當(dāng)前結(jié)點(diǎn)的等待狀態(tài)
 
 volatile Node prev;  //表示同步隊(duì)列中的前繼結(jié)點(diǎn)
 
 volatile Node next;  //表示同步隊(duì)列中的后繼結(jié)點(diǎn)
 
 volatile Thread thread; //當(dāng)前結(jié)點(diǎn)持有的線程引用
 
 Node nextWaiter;   //表示條件隊(duì)列中的后繼結(jié)點(diǎn)
 
 //當(dāng)前結(jié)點(diǎn)狀態(tài)是否是共享模式
 final boolean isShared() {
  return nextWaiter == SHARED;
 }
 
 //返回當(dāng)前結(jié)點(diǎn)的前繼結(jié)點(diǎn)
 final Node predecessor() throws NullPointerException {
  Node p = prev;
  if (p == null) {
   throw new NullPointerException();
  } else {
   return p;
  }
 }
 
 //構(gòu)造器1
 Node() {}
 
 //構(gòu)造器2, 默認(rèn)用這個(gè)構(gòu)造器
 Node(Thread thread, Node mode) {
  //注意持有模式是賦值給nextWaiter
  this.nextWaiter = mode;
  this.thread = thread;
 }
 
 //構(gòu)造器3, 只在條件隊(duì)列中用到
 Node(Thread thread, int waitStatus) {
  this.waitStatus = waitStatus;
  this.thread = thread;
 }
}

Node代表同步隊(duì)列和條件隊(duì)列中的一個(gè)結(jié)點(diǎn),它是AbstractQueuedSynchronizer的內(nèi)部類。Node有很多屬性,比如持有模式,等待狀態(tài),同步隊(duì)列中的前繼和后繼,以及條件隊(duì)列中的后繼引用等等。可以把同步隊(duì)列和條件隊(duì)列看成是排隊(duì)區(qū),每個(gè)結(jié)點(diǎn)看成是排隊(duì)區(qū)的座位,將線程看成是排隊(duì)的客人。客人剛來(lái)時(shí)會(huì)先去敲敲門,看看鎖有沒有開,如果鎖沒開它就會(huì)去排隊(duì)區(qū)領(lǐng)取一個(gè)號(hào)碼牌,聲明自己想要以什么樣的方式來(lái)持有鎖,最后再到隊(duì)列的末尾進(jìn)行排隊(duì)。

4 怎樣理解獨(dú)占模式和共享模式?

前面講到每個(gè)客人在排隊(duì)前會(huì)領(lǐng)取一個(gè)號(hào)碼牌,聲明自己想要以什么樣的方式來(lái)占有鎖,占有鎖的方式分為獨(dú)占模式和共享模式,那么怎樣來(lái)理解獨(dú)占模式和共享模式呢?實(shí)在找不到什么好的比喻,大家可以聯(lián)想一下公共廁所,獨(dú)占模式的人比較霸道,老子要么就不進(jìn),進(jìn)來(lái)了就不許別人再進(jìn)了,自己一個(gè)人獨(dú)自占用整個(gè)廁所。共享模式的人就沒那么講究了,當(dāng)它發(fā)現(xiàn)這個(gè)廁所已經(jīng)可以用了之后,它自己進(jìn)來(lái)還不算,還得熱心的問下后面的人介不介意一起用,如果后面的人不介意一起使用那就不用再排隊(duì)了大家一起上就是了, 當(dāng)然如果后面的人介意那就只好留在隊(duì)列里繼續(xù)排隊(duì)了。

5 怎樣理解結(jié)點(diǎn)的等待狀態(tài)?

我們還看到每個(gè)結(jié)點(diǎn)都有一個(gè)等待狀態(tài),這個(gè)等待狀態(tài)分為CANCELLED,SIGNAL,CONDITION,PROPAGATE四種狀態(tài)。可以將這個(gè)等待狀態(tài)看作是掛在座位旁邊的牌子,標(biāo)識(shí)當(dāng)前座位上的人的等待狀態(tài)。這個(gè)牌子的狀態(tài)不僅自己可以修改,其他人也可以修改。例如當(dāng)這個(gè)線程在排隊(duì)過(guò)程中已經(jīng)打算放棄了,它就會(huì)將自己座位上的牌子設(shè)置為CANCELLED,這樣其他人看到了就可以將它清理出隊(duì)列。還有一種情況是,當(dāng)線程在座位上要睡著之前,它怕自己睡過(guò)了頭,就會(huì)將前面位置上的牌子改為SIGNAL,因?yàn)槊總€(gè)人在離開隊(duì)列前都會(huì)回到自己座位上看一眼,如果看到牌子上狀態(tài)為SIGNAL,它就會(huì)去喚醒下一個(gè)人。只有保證前面位置上的牌子為SIGNAL,當(dāng)前線程才會(huì)安心的睡去。CONDITION狀態(tài)表示該線程在條件隊(duì)列中排隊(duì),PROPAGATE狀態(tài)提醒后面來(lái)的線程可以直接獲取鎖,這個(gè)狀態(tài)只在共享模式用到,后面單獨(dú)講共享模式的時(shí)候會(huì)講到。

6. 結(jié)點(diǎn)進(jìn)入同步隊(duì)列時(shí)會(huì)進(jìn)行哪些操作?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//結(jié)點(diǎn)入隊(duì)操作, 返回前一個(gè)結(jié)點(diǎn)
private Node enq(final Node node) {
 for (;;) {
  //獲取同步隊(duì)列尾結(jié)點(diǎn)引用
  Node t = tail;
  //如果尾結(jié)點(diǎn)為空說(shuō)明同步隊(duì)列還沒有初始化
  if (t == null) {
   //初始化同步隊(duì)列
   if (compareAndSetHead(new Node())) {
    tail = head;
   }
  } else {
   //1.指向當(dāng)前尾結(jié)點(diǎn)
   node.prev = t;
   //2.設(shè)置當(dāng)前結(jié)點(diǎn)為尾結(jié)點(diǎn)
   if (compareAndSetTail(t, node)) {
    //3.將舊的尾結(jié)點(diǎn)的后繼指向新的尾結(jié)點(diǎn)
    t.next = node;
    //for循環(huán)唯一的出口
    return t;
   }
  }
 }
}

注意,入隊(duì)操作使用一個(gè)死循環(huán),只有成功將結(jié)點(diǎn)添加到同步隊(duì)列尾部才會(huì)返回,返回結(jié)果是同步隊(duì)列原先的尾結(jié)點(diǎn)。下圖演示了整個(gè)操作過(guò)程。

Java并發(fā)系列之AbstractQueuedSynchronizer源碼分析(概要分析)

讀者需要注意添加尾結(jié)點(diǎn)的順序,分為三步:指向尾結(jié)點(diǎn),CAS更改尾結(jié)點(diǎn),將舊尾結(jié)點(diǎn)的后繼指向當(dāng)前結(jié)點(diǎn)。在并發(fā)環(huán)境中這三步操作不一定能保證完成,所以在清空同步隊(duì)列所有已取消的結(jié)點(diǎn)這一操作中,為了尋找非取消狀態(tài)的結(jié)點(diǎn),不是從前向后遍歷而是從后向前遍歷的。還有就是每個(gè)結(jié)點(diǎn)進(jìn)入隊(duì)列中時(shí)它的等待狀態(tài)是為0,只有后繼結(jié)點(diǎn)的線程需要掛起時(shí)才會(huì)將前面結(jié)點(diǎn)的等待狀態(tài)改為SIGNAL。

注:以上全部分析基于JDK1.7,不同版本間會(huì)有差異,讀者需要注意。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:http://www.cnblogs.com/liuyun1995/p/8400663.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 永久91嫩草亚洲精品人人 | 香蕉久久夜色精品国产使用方法 | 成人精品一区二区 | 亚洲一区二区三区免费观看 | 亚洲成人一区二区 | 精品久久久久久久久久久久久久 | 黄色片免费在线 | 免费成人av片 | 国产精品久久久久久久一区探花 | 久久久久久久久久久高潮 | 久久久久成人精品 | 亚洲黄色成人 | 欧美激情亚洲 | 最新一级毛片 | 欧州一区二区三区 | 亚洲精品一区二区三区在线观看 | 久久99精品国产99久久6尤 | 最新中文字幕视频 | 亚洲综合色视频在线观看 | 成人午夜视频免费 | 亚洲精品一区二区三区蜜桃久 | 最近高清无吗免费看 | 久久男人天堂 | 精品视频在线播放 | 久久99er6热线精品首页蜜臀 | 不卡免费在线视频 | 亚洲精品乱码 | 一级做a爰片久久毛片免费陪 | 欧美视频精品 | 亚洲一区二区在线播放 | 日韩精品视频在线 | 久久男人网 | 精品国产91亚洲一区二区三区www | av一区二区三区四区 | av电影在线播放 | 久久成人精品视频 | 午夜视频在线 | 久久久精品网 | 欧美成人精品一区二区三区 | 免费三级国产 | 黄a视频|