• java共享锁实现原理及CountDownLatch解析


    转 http://blog.csdn.net/yanyan19880509/article/details/52349056

    前言

    前面介绍了ReentrantLock,又叫排他锁,本篇主要通过CountDownLatch的学习来了解java并发包中是如何实现共享锁的。

    CountDownLatch使用解说

    CountDownLatch是java5中新增的一个并发工具类,其使用非常简单,下面通过伪代码简单看一下使用方式:

    这是一个使用CountDownLatch非常简单的例子,创建的时候,需要指定一个初始状态值,本例为2,

    主线程调用 latch.await时,除非latch状态值为0,否则会一直阻塞休眠。当所有任务执行完后,主线程唤醒,最终执行打印动作。

    以上只是一个最简单的例子,接着咱们再来看一个,这回,咱们想要在任务执行完后做更多的事情,如下图所示:

    这一次,在线程3和线程4中,分别调用了latch.await(),当latch状态值为0时,这两个线程将会继续执行任务,但是顺序性是无法保证的。

    CountDownLatch的方便之处在于,你可以在一个线程中使用,也可以在多个线程上使用,一切只依据状态值,这样便不会受限于任何的场景。

    java共享锁模型

    在java5提供的并发包下,有一个AbstractQueuedSynchronizer抽象类,也叫AQS,此类根据大部分并发共性作了一些抽象,

    便于开发者实现如排他锁,共享锁,条件等待等更高级的业务功能。它通过使用CAS和队列模型,出色的完成了抽象任务,在此向Doug Lea致敬。

    AQS比较抽象,并且是优化精简的代码,如果一头扎进去,可能会比较容易迷失。本篇只解说CountDownLatch中使用到的共享锁模型。

    我们以CountDownLatch第二个例子作为案例来分析一下,一开始,我们创建了一个CountDownLatch实例,

    此时,AQS中,状态值state=2,对于 CountDownLatch 来说,state=2表示所有调用await方法的线程都应该阻塞,

    等到同一个latch被调用两次countDown后才能唤醒沉睡的线程。接着线程3和线程4执行了 await方法,这会的状态图如下:

    注意,上面的通知状态是节点的属性,表示该节点出队后,必须唤醒其后续的节点线程。

    当线程1和线程2分别执行完latch.countDown方法后,会把state值置为0,此时,通过CAS成功置为0的那个线程将会同时承担起唤醒队列中第一个节点线程的任务,从上图可以看出,第一个节点即为线程3,当线程3恢复执行之后,其发现状态值为通知状态,所以会唤醒后续节点,即线程4节点,然后线程3继续做自己的事情,到这里,线程3和线程4都已经被唤醒,CountDownLatch功成身退。

    上面的流程,如果落实到代码,把 state置为0的那个线程,会判断head指向节点的状态,

    如果为通知状态,则唤醒后续节点,即线程3节点,然后head指向线程3节点,head指向的旧节点会被删除掉。

    当线程3恢复执行后,发现自身为通知状态,又会把head指向线程4节点,然后删除自身节点,并唤醒 线程4。

    这里可能读者会有个疑问,线程节点的状态是什么时候设置上去的。

    其实,一个线程在阻塞之前,就会把它前面的节点设置为通知状态,这样便可以实现链式唤醒机制了。

    结束语

    本篇从CountDownLatch入手讲解AQS中的共享锁模式,主要是由CountDownLatch的实现相对简单,

    但却实现了共享锁模型,如果在理解了模型的基础上,从CountDownLatch入手来看AQS关于共享锁的代码还比较好看懂,

    在看的时候,建议以看懂大致内容为主,学习其设计的思路,不要陷入所有条件处理细节中,多线程环境中,对与错有时候不是那么容易看出来的。

  • 相关阅读:
    shell (3) 磁盘挂载
    QByteArray 内存拷贝异常
    记录QTextEdit
    QTableWidget 使用
    QT 读写xml
    远程工具长时间待机断网解决办法
    qt读写json文件
    QT 资源文件(.qrc)
    error: C1041: 无法打开程序数据库“E:ProjectQtuild-QCaculator-Desktop_Qt_5_14_1_MSVC2017_32_bit-DebugdebugQCaculator.vc.pdb”;如果要将多个 CL.EXE 写入同一个 .PDB 文件,请使用 /FS
    Vs2019+Qt5.14环境配置,安装qt visual studio tools报错。
  • 原文地址:https://www.cnblogs.com/faunjoe88/p/7922113.html
Copyright © 2020-2023  润新知