欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java concurrency之公平鎖(二)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

 更新時(shí)間:2017年06月12日 15:48:08   作者:skywang12345  
這篇文章主要為大家詳細(xì)介紹了Java concurrency之公平鎖的第二篇內(nèi)容,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

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

1. unlock()

unlock()在ReentrantLock.java中實(shí)現(xiàn)的,源碼如下:

public void unlock() {
  sync.release(1);
}

說(shuō)明:

unlock()是解鎖函數(shù),它是通過(guò)AQS的release()函數(shù)來(lái)實(shí)現(xiàn)的。
在這里,“1”的含義和“獲取鎖的函數(shù)acquire(1)的含義”一樣,它是設(shè)置“釋放鎖的狀態(tài)”的參數(shù)。由于“公平鎖”是可重入的,所以對(duì)于同一個(gè)線程,每釋放鎖一次,鎖的狀態(tài)-1。

關(guān)于AQS, ReentrantLock 和 sync的關(guān)系如下:

public class ReentrantLock implements Lock, java.io.Serializable {

  private final Sync sync;

  abstract static class Sync extends AbstractQueuedSynchronizer {
    ...
  }

  ...
}

從中,我們發(fā)現(xiàn):sync是ReentrantLock.java中的成員對(duì)象,而Sync是AQS的子類(lèi)。 

2. release()

release()在AQS中實(shí)現(xiàn)的,源碼如下:

public final boolean release(int arg) {
  if (tryRelease(arg)) {
    Node h = head;
    if (h != null && h.waitStatus != 0)
      unparkSuccessor(h);
    return true;
  }
  return false;
}

說(shuō)明:

release()會(huì)先調(diào)用tryRelease()來(lái)嘗試釋放當(dāng)前線程鎖持有的鎖。成功的話,則喚醒后繼等待線程,并返回true。否則,直接返回false。 

3. tryRelease()

tryRelease()在ReentrantLock.java的Sync類(lèi)中實(shí)現(xiàn),源碼如下:

protected final boolean tryRelease(int releases) {
  // c是本次釋放鎖之后的狀態(tài)
  int c = getState() - releases;
  // 如果“當(dāng)前線程”不是“鎖的持有者”,則拋出異常!
  if (Thread.currentThread() != getExclusiveOwnerThread())
    throw new IllegalMonitorStateException();

  boolean free = false;
  // 如果“鎖”已經(jīng)被當(dāng)前線程徹底釋放,則設(shè)置“鎖”的持有者為null,即鎖是可獲取狀態(tài)。
  if (c == 0) {
    free = true;
    setExclusiveOwnerThread(null);
  }
  // 設(shè)置當(dāng)前線程的鎖的狀態(tài)。
  setState(c);
  return free;
}

說(shuō)明:

tryRelease()的作用是嘗試釋放鎖。
(01) 如果“當(dāng)前線程”不是“鎖的持有者”,則拋出異常。
(02) 如果“當(dāng)前線程”在本次釋放鎖操作之后,對(duì)鎖的擁有狀態(tài)是0(即,當(dāng)前線程徹底釋放該“鎖”),則設(shè)置“鎖”的持有者為null,即鎖是可獲取狀態(tài)。同時(shí),更新當(dāng)前線程的鎖的狀態(tài)為0。
getState(), setState()在前一章已經(jīng)介紹過(guò),這里不再說(shuō)明。
getExclusiveOwnerThread(), setExclusiveOwnerThread()在AQS的父類(lèi)AbstractOwnableSynchronizer.java中定義,源碼如下:

public abstract class AbstractOwnableSynchronizer
  implements java.io.Serializable {

  // “鎖”的持有線程
  private transient Thread exclusiveOwnerThread;

  // 設(shè)置“鎖的持有線程”為t
  protected final void setExclusiveOwnerThread(Thread t) {
    exclusiveOwnerThread = t;
  }

  // 獲取“鎖的持有線程”
  protected final Thread getExclusiveOwnerThread() {
    return exclusiveOwnerThread;
  }
  
  ...
}

4. unparkSuccessor()

在release()中“當(dāng)前線程”釋放鎖成功的話,會(huì)喚醒當(dāng)前線程的后繼線程。
根據(jù)CLH隊(duì)列的FIFO規(guī)則,“當(dāng)前線程”(即已經(jīng)獲取鎖的線程)肯定是head;如果CLH隊(duì)列非空的話,則喚醒鎖的下一個(gè)等待線程。

下面看看unparkSuccessor()的源碼,它在AQS中實(shí)現(xiàn)。

private void unparkSuccessor(Node node) {
  // 獲取當(dāng)前線程的狀態(tài)
  int ws = node.waitStatus;
  // 如果狀態(tài)<0,則設(shè)置狀態(tài)=0
  if (ws < 0)
    compareAndSetWaitStatus(node, ws, 0);

  //獲取當(dāng)前節(jié)點(diǎn)的“有效的后繼節(jié)點(diǎn)”,無(wú)效的話,則通過(guò)for循環(huán)進(jìn)行獲取。
  // 這里的有效,是指“后繼節(jié)點(diǎn)對(duì)應(yīng)的線程狀態(tài)<=0”
  Node s = node.next;
  if (s == null || s.waitStatus > 0) {
    s = null;
    for (Node t = tail; t != null && t != node; t = t.prev)
      if (t.waitStatus <= 0)
        s = t;
  }
  // 喚醒“后繼節(jié)點(diǎn)對(duì)應(yīng)的線程”
  if (s != null)
    LockSupport.unpark(s.thread);
}

說(shuō)明:

unparkSuccessor()的作用是“喚醒當(dāng)前線程的后繼線程”。后繼線程被喚醒之后,就可以獲取該鎖并恢復(fù)運(yùn)行了。

關(guān)于node.waitStatus的說(shuō)明,請(qǐng)參考“上一章關(guān)于Node類(lèi)的介紹”。

 總結(jié)

“釋放鎖”的過(guò)程相對(duì)“獲取鎖”的過(guò)程比較簡(jiǎn)單。釋放鎖時(shí),主要進(jìn)行的操作,是更新當(dāng)前線程對(duì)應(yīng)的鎖的狀態(tài)。如果當(dāng)前線程對(duì)鎖已經(jīng)徹底釋放,則設(shè)置“鎖”的持有線程為null,設(shè)置當(dāng)前線程的狀態(tài)為空,然后喚醒后繼線程。

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

相關(guān)文章

  • Java 中ConcurrentHashMap的實(shí)現(xiàn)

    Java 中ConcurrentHashMap的實(shí)現(xiàn)

    本文主要介紹Java 中ConcurrentHashMap的實(shí)現(xiàn),這里整理了詳細(xì)的資料,及簡(jiǎn)單實(shí)例代碼,有興趣的小伙伴可以參考下
    2016-09-09
  • java實(shí)現(xiàn)OpenGL ES紋理映射的方法

    java實(shí)現(xiàn)OpenGL ES紋理映射的方法

    這篇文章主要介紹了java實(shí)現(xiàn)OpenGL ES紋理映射的方法,以實(shí)例形式較為詳細(xì)的分析了紋理映射的實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2015-06-06
  • java實(shí)現(xiàn)科研信息管理系統(tǒng)

    java實(shí)現(xiàn)科研信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java科研信息管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • springboot中如何判斷某個(gè)bean是否存在

    springboot中如何判斷某個(gè)bean是否存在

    這篇文章主要介紹了springboot中如何判斷某個(gè)bean是否存在,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • OpenFeign實(shí)現(xiàn)遠(yuǎn)程調(diào)用

    OpenFeign實(shí)現(xiàn)遠(yuǎn)程調(diào)用

    這篇文章主要為大家詳細(xì)介紹了OpenFeign實(shí)現(xiàn)遠(yuǎn)程調(diào)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • 一篇文章帶你入門(mén)java網(wǎng)絡(luò)編程

    一篇文章帶你入門(mén)java網(wǎng)絡(luò)編程

    網(wǎng)絡(luò)編程是指編寫(xiě)運(yùn)行在多個(gè)設(shè)備(計(jì)算機(jī))的程序,這些設(shè)備都通過(guò)網(wǎng)絡(luò)連接起來(lái)。本文介紹了一些網(wǎng)絡(luò)編程基礎(chǔ)的概念,并用Java來(lái)實(shí)現(xiàn)TCP和UDP的Socket的編程,來(lái)讓讀者更好的了解其原理
    2021-08-08
  • 劍指Offer之Java算法習(xí)題精講數(shù)組查找與字符串交集

    劍指Offer之Java算法習(xí)題精講數(shù)組查找與字符串交集

    跟著思路走,之后從簡(jiǎn)單題入手,反復(fù)去看,做過(guò)之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化
    2022-03-03
  • Java實(shí)現(xiàn)解析dcm醫(yī)學(xué)影像文件并提取文件信息的方法示例

    Java實(shí)現(xiàn)解析dcm醫(yī)學(xué)影像文件并提取文件信息的方法示例

    這篇文章主要介紹了Java實(shí)現(xiàn)解析dcm醫(yī)學(xué)影像文件并提取文件信息的方法,結(jié)合實(shí)例形式分析了java基于第三方庫(kù)文件針對(duì)dcm醫(yī)學(xué)影像文件的解析操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2018-04-04
  • IntelliJ IDEA中新建Java class的解決方案

    IntelliJ IDEA中新建Java class的解決方案

    今天小編就為大家分享一篇關(guān)于IntelliJ IDEA中新建Java class的解決方案,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-10-10
  • SpringBoot實(shí)現(xiàn)RabbitMQ監(jiān)聽(tīng)消息的四種方式

    SpringBoot實(shí)現(xiàn)RabbitMQ監(jiān)聽(tīng)消息的四種方式

    本文主要介紹了SpringBoot實(shí)現(xiàn)RabbitMQ監(jiān)聽(tīng)消息的四種方式,包括@RabbitListener,MessageListener接口,MessageListenerAdapter適配器,@RabbitHandler這幾種,感興趣的可以了解一下
    2024-05-05

最新評(píng)論