一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

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

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

服務器之家 - 編程語言 - Java教程 - Java concurrency之非公平鎖_動力節點Java學院整理

Java concurrency之非公平鎖_動力節點Java學院整理

2020-11-15 20:09skywang12345 Java教程

本篇文章主要介紹了Java concurrency之非公平鎖,詳細的介紹了獲取和釋放非公平鎖,有興趣的同學可以了解一下

獲取非公平鎖(基于JDK1.7.0_40)

非公平鎖和公平鎖在獲取鎖的方法上,流程是一樣的;它們的區別主要表現在“嘗試獲取鎖的機制不同”。簡單點說,“公平鎖”在每次嘗試獲取鎖時,都是采用公平策略(根據等待隊列依次排序等待);而“非公平鎖”在每次嘗試獲取鎖時,都是采用的非公平策略(無視等待隊列,直接嘗試獲取鎖,如果鎖是空閑的,即可獲取狀態,則獲取鎖)。 

1. lock()

?
1
2
3
4
5
6
7
lock()在ReentrantLock.java的NonfairSync類中實現,它的源碼如下:
final void lock() {
  if (compareAndSetState(0, 1))
    setExclusiveOwnerThread(Thread.currentThread());
  else
    acquire(1);
}

說明:

lock()會先通過compareAndSet(0, 1)來判斷“鎖”是不是空閑狀態。是的話,“當前線程”直接獲取“鎖”;否則的話,調用acquire(1)獲取鎖。

(01) compareAndSetState()是CAS函數,它的作用是比較并設置當前鎖的狀態。若鎖的狀態值為0,則設置鎖的狀態值為1。

(02) setExclusiveOwnerThread(Thread.currentThread())的作用是,設置“當前線程”為“鎖”的持有者。

“公平鎖”和“非公平鎖”關于lock()的對比

  1. 公平鎖   -- 公平鎖的lock()函數,會直接調用acquire(1)。
  2. 非公平鎖 -- 非公平鎖會先判斷當前鎖的狀態是不是空閑,是的話,就不排隊,而是直接獲取鎖。

2. acquire()

acquire()在AQS中實現的,它的源碼如下:

?
1
2
3
4
5
public final void acquire(int arg) {
  if (!tryAcquire(arg) &&
    acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
    selfInterrupt();
}

(01) “當前線程”首先通過tryAcquire()嘗試獲取鎖。獲取成功的話,直接返回;嘗試失敗的話,進入到等待隊列依次排序,然后獲取鎖。

(02) “當前線程”嘗試失敗的情況下,會先通過addWaiter(Node.EXCLUSIVE)來將“當前線程”加入到"CLH隊列(非阻塞的FIFO隊列)"末尾。

(03) 然后,調用acquireQueued()獲取鎖。在acquireQueued()中,當前線程會等待它在“CLH隊列”中前面的所有線程執行并釋放鎖之后,才能獲取鎖并返回。如果“當前線程”在休眠等待過程中被中斷過,則調用selfInterrupt()來自己產生一個中斷。

“公平鎖”和“非公平鎖”關于acquire()的對比

公平鎖和非公平鎖,只有tryAcquire()函數的實現不同;即它們嘗試獲取鎖的機制不同。這就是我們所說的“它們獲取鎖策略的不同所在之處”!

非公平鎖的tryAcquire()在ReentrantLock.java的NonfairSync類中實現,源碼如下:

?
1
2
3
protected final boolean tryAcquire(int acquires) {
  return nonfairTryAcquire(acquires);
}

nonfairTryAcquire()在ReentrantLock.java的Sync類中實現,源碼如下:

?
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
final boolean nonfairTryAcquire(int acquires) {
  // 獲取“當前線程”
  final Thread current = Thread.currentThread();
  // 獲取“鎖”的狀態
  int c = getState();
  // c=0意味著“鎖沒有被任何線程鎖擁有”
  if (c == 0) {
    // 若“鎖沒有被任何線程鎖擁有”,則通過CAS函數設置“鎖”的狀態為acquires。
    // 同時,設置“當前線程”為鎖的持有者。
    if (compareAndSetState(0, acquires)) {
      setExclusiveOwnerThread(current);
      return true;
    }
  }
  else if (current == getExclusiveOwnerThread()) {
    // 如果“鎖”的持有者已經是“當前線程”,
    // 則將更新鎖的狀態。
    int nextc = c + acquires;
    if (nextc < 0) // overflow
      throw new Error("Maximum lock count exceeded");
    setState(nextc);
    return true;
  }
  return false;
}

說明:

根據代碼,我們可以分析出,tryAcquire()的作用就是嘗試去獲取鎖。

(01) 如果“鎖”沒有被任何線程擁有,則通過CAS函數設置“鎖”的狀態為acquires,同時,設置“當前線程”為鎖的持有者,然后返回true。

(02) 如果“鎖”的持有者已經是當前線程,則將更新鎖的狀態即可。

(03) 如果不術語上面的兩種情況,則認為嘗試失敗。

“公平鎖”和“非公平鎖”關于tryAcquire()的對比
公平鎖和非公平鎖,它們嘗試獲取鎖的方式不同。

公平鎖在嘗試獲取鎖時,即使“鎖”沒有被任何線程鎖持有,它也會判斷自己是不是CLH等待隊列的表頭;是的話,才獲取鎖。

而非公平鎖在嘗試獲取鎖時,如果“鎖”沒有被任何線程持有,則不管它在CLH隊列的何處,它都直接獲取鎖。

釋放非公平鎖(基于JDK1.7.0_40)

非公平鎖和公平鎖在釋放鎖的方法和策略上是一樣的。

總結

公平鎖和非公平鎖的區別,是在獲取鎖的機制上的區別。表現在,在嘗試獲取鎖時 —— 公平鎖,只有在當前線程是CLH等待隊列的表頭時,才獲取鎖;而非公平鎖,只要當前鎖處于空閑狀態,則直接獲取鎖,而不管CLH等待隊列中的順序。

只有當非公平鎖嘗試獲取鎖失敗的時候,它才會像公平鎖一樣,進入CLH等待隊列排序等待。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩色图区 | 99re8在这里只有精品23 | 国产欧美日韩精品高清二区综合区 | 韩国女主播在线大尺无遮挡 | 日韩理论片在线看免费观看 | 午夜精品久久久久久久99 | 国产成人亚洲影视在线 | 猥琐对着美女飞机喷到脸上 | 国产精品天天影视久久综合网 | 欧美国产视频 | 青青青在线免费 | 久久精品国产亚洲AV麻豆欧美玲 | 91九色porny国产美女一区 | 亚洲香蕉网久久综合影院3p | 动漫美女被褥吸奶漫画漫画 | 美女把小内内脱个精光打屁屁 | 我的好妈妈7中字在线观看韩国 | 蜜桃成人影院 | 精品视频在线免费播放 | 精品国偷自产在线 | 紧身裙女教师波多野结衣 | 国产综合久久久久 | 精品在线免费观看 | 精品久久久久久综合网 | 女人张开腿 让男人桶个爽 免费观看 | 无颜之月5集全免费看无删除 | 免费一级欧美片在线观免看 | 亚洲精品一区二区三区中文字幕 | www在线观看视频免费 | 亚瑟天堂久久一区二区影院 | 天天做日日做 | 亚洲男人的天堂成人 | 欧美成年黄网站色高清视频 | 午夜第一页 | 成人影院在线观看 | 高h视频免费观看 | japanese日本护士| 日本人泡妞18xxⅹ | 五月九九 | 国产区香蕉精品系列在线观看不卡 | 亚洲日本久久一区二区va |