Java并发同步器AQS(AbstractQueuedSynchronizer)学习笔记(1)

Java中的并发包,是在Java代码中并发程序的热门话题。如果我们去读concurrent包的源码时,会发现其真正的核心是 AbstractQueuedSynchronizer , 简称 AQS 框架 , 而 Doug Lea 大神正是此包的作者。

之前也看过一遍 AbstractQueuedSynchronize,但印象不深,只有依稀的印象。这次重新学习一遍,并整理出笔记,希望对自己或者是别人有用。当然了,笔者也是浅显的过一遍,很多细节也并不是完全理解。

建议读者先看这个系列的文章:Inside AbstractQueuedSynchronizer,之后再继续本篇。

首先,AQS会对进行 acquire 而被阻塞的线程进行管理,说是管理,其实就是内部维护了一个FIFO队列,这个队列是一个双向链表。链头可以理解为是一个空的节点,除了链头以外,每个节点内部都持有着一个线程,同时,有着两个重要的字段:waitStatus 和 nextWaiter。nextWaiter一般是作用与在使用Condition时的队列。而waitStatus则有以下几个字段:

  • SIGNAL 表示下一个节点应该被唤醒。为什么是下一个节点?因为刚刚说了,这个FIFO队列,链头都是一个空的节点,但此节点的 waitStatus 正好就表示了要对下一节点做的事情

  • CANCELLED 表示此节点持有的线程被中断,或者该线程为null了。节点只能是暂时停留在此状态,因为在线程进入AQS时,线程会找机会整理链表,包括删除CANCELLED状态的节点。

  • CONDITION 表示此节点是在另一个队列中 —— condition队列中。比如我们使用的ReentrantLock.newCondition()获得Condition对象进行await时,在AQS内部所产生的节点。

  • PROPAGATE 顾名思义,传播。这点比较难理解,需要仔细推敲。因为此状态是为共享同步器使用的。加入此状态,可以避免无谓的线程 park 和 unpark。按照我对代码的理解,这是对多个线程并发获取共享同步器(比如acquireShared)所进行的优化,至少有3个线程并发,但想要优化效果明显的话,可能需要几十个线程并发的获取共享同步器(比如acquireShared),如果在并发量非常大的时候,对系统的吞吐量的作用应该不少。

AbstractQueuedSynchronizer内置一个state字段,用来表示某种意义——当ReentrantLock使用AQS的时候,state被用来表示锁被重入的次数;当’Semaphore’使用AQS的时候,state则被用来表示当前还有多少信号量可被获取。

AbstractQueuedSynchronizer 支持两种模式,分别是独占式和共享式。两者进行获取和释放动作的思路都是差不多的。

获取同步器的流程如下:

<!-- lang: java -->
if(尝试获取成功){
    return;
 }else{
     加入等待队列;park自己
}

释放同步器的流程如下:

<!-- lang: java -->
if(尝试释放成功){
    unpark等待队列中第一个节点
}else{
    return false
}

只要环绕着这两个思路去看AQS中的代码,相信应该可以明白其中的主要原理。

原文在我的博客上:Java并发同步器AQS(AbstractQueuedSynchronizer)学习笔记(1)

转载于:https://my.oschina.net/zavakid/blog/84882

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值