码迷,mamicode.com
首页 > 编程语言 > 详细

java并发编程的艺术(三)---lock源码

时间:2018-12-30 23:18:52      阅读:277      评论:0      收藏:0      [点我收藏+]

标签:队列   str   nbsp   同步   一个   alt   过程   艺术   运行   

 

jdk1.5以后,并发包中新增了lock接口,

它相对于synchronized,多了以下三个主要特性:尝试非阻塞地获取锁(尝试获取锁成功则持有)、能被中断地获取锁(锁的进程能响应中断)、超时获取锁(指定时间截止之前获取锁)。

我们看看它接口中定义的api:

技术分享图片获取锁

技术分享图片可中断地获取锁

技术分享图片尝试非阻塞地获取锁,能够获取则返回true,否则false

技术分享图片超时获取锁,三种返回情况:1、当前线程在超时时间内获得了锁。2、当前线程在超时时间内被中断。3、超时时间内没获得锁

技术分享图片释放锁

技术分享图片获取等待通知组件,该组件和当前的锁绑定,当前线程只有获得了锁,才能调用该组件的wait()方法,而调用后,当前线程将释放锁。

java中lock的实现是ReentrantLock

 观测其源码,我们可以发现,lock接口的所有实现方法均是通过一个AbstractQueuedSynchronizer(同步器)的对象实现的

技术分享图片

队列同步器是用来构建锁或者其他同步组件的基础框架,使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。

他有三个方法改变状态

技术分享图片

技术分享图片

getState():获取当前同步状态

setState():设置当前同步状态

compareAndSetState(): 使用CAS设置当前状态,保证原子性

同步器中的队列使用了一个双向队列来管理同步状态

技术分享图片

技术分享图片

技术分享图片

 

每个队列元素都有三种状态: cancelled:1 等待的线程超时或者被中断,将取消等待变成该状态(已取消)

signal: -1 下一个节点处于等待状态,当前节点若是释放了同步状态或者被取消了,将通知后继节点得以运行

condition: -2 节点在等待队列中,等待在condition上,其他线程对condition调用了signal()方法后,该节点将从等待队列中转移到同步队列中,加入到对同步状态的获取中。

propagate: -3 传播共享式同步状态

initial: 0 初始状态

主要对象:

node prev:前驱节点

node next:后继节点

node nextWaiter: 等待队列中的后继节点。

Thread thread: 获取同步状态的线程

技术分享图片

同步器中存储着头节点head跟尾节点tail。

源码中实现lock的方法,是调用了同步器中的acquire(int arg)(独占式同步状态)方法

技术分享图片

该方法尝试独占获取同步状态,成功则返回,否则进入同步队列等待

技术分享图片

 技术分享图片

技术分享图片

通过死循环来保证节点的正确添加(CAS)

 技术分享图片

节点进入同步队列后,进入一个自旋的过程,当获得同步状态则调用release从自旋退出,并唤醒头节点的后继节点

技术分享图片

独占式同步状态总结: 获取同步状态失败的线程会进入到同步器队列中进行自旋,移除队列的条件是前驱节点为头节点且成功获取了同步状态,在释放同步状态时候,同步器会调用tryRelease()方法释放同步状态并且唤醒后继节点。

共享式同步状态:主要用在读写操作上,多线程可以同时读,但是写锁会排他。

同步器中的acquireShared()方法就是以共享式地获取同步状态

技术分享图片

我们可以看到在ReentrantReadWriteLock中的读锁ReadLock中的lock()方法

技术分享图片

调用了同步器中的共享式获取同步状态,而写锁writeLock中则调用了独占式方法

技术分享图片

 

java并发编程的艺术(三)---lock源码

标签:队列   str   nbsp   同步   一个   alt   过程   艺术   运行   

原文地址:https://www.cnblogs.com/wengshuhang/p/10200992.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!