zoukankan      html  css  js  c++  java
  • 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关于共享锁的代码还比较好看懂,

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

  • 相关阅读:
    扫面线模板
    (动态规划、栈)leetcode 84. Largest Rectangle in Histogram, 85. Maximal Rectangle
    tmux 常见命令汇总
    leetcode 221
    leetcode 319 29
    (贪心)leetcode 392. Is Subsequence, 771. Jewels and Stones, 463. Island Perimeter
    leetcode 982 668
    Python import 同文件夹下的py文件的函数,pycharm报错
    Windows里Anaconda-Navigator无法打开的解决方案
    Windows下 gpu版 Tensorflow 安装
  • 原文地址:https://www.cnblogs.com/faunjoe88/p/7922113.html
Copyright © 2011-2022 走看看