实战Java高并发程序设计之ReentrantLock(二)
来源:互联网 发布:linux下usb通讯编程 编辑:程序博客网 时间:2024/05/29 04:48
前面讲到了ReentranLock的基本使用,现在来看看它的底层实现.
先看ReentrantLok的UML类图(图片来自:http://www.cnblogs.com/skywang12345/p/3496147.html)
ReentrantLock实现了Lock接口.内部维持着一个Sync对象.
/** * 该锁基于同步控制. 分为公平锁和非公平锁. * 使用AQS状态来表示锁上的保留数量.0表示无锁 */ abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; //抽象的lock方法,交给子类去实现 abstract void lock(); /** * 执行不公平的tryLock. tryAcquire在子类中实现, 都需要不公平锁去尝试tryLock() */ final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); //获取当前同步的状态值 int c = getState(); //0表示该锁处于可获取状态 if (c == 0) { if (compareAndSetState(0, acquires)) { //设置当前线程为当前拥有“独占锁”的线程 setExclusiveOwnerThread(current); return true; } } //如果当前线程为独占锁所持有的线程 else if (current == getExclusiveOwnerThread()) { //设置新状态 int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } /** * 释放锁 */ protected final boolean tryRelease(int releases) { //设置释放锁以后的状态 int c = getState() - releases; //如果当前线程不是当前独占锁所持有的线程 if (Thread.currentThread() != getExclusiveOwnerThread()) //抛出状态监听异常 throw new IllegalMonitorStateException(); boolean free = false; //状态为0时,表示无锁 if (c == 0) { free = true; //设置独占锁线程为空 setExclusiveOwnerThread(null); } setState(c); return free; } /** * 判断当前线程是否被当前独占锁持有 */ protected final boolean isHeldExclusively() { return getExclusiveOwnerThread() == Thread.currentThread(); } final ConditionObject newCondition() { return new ConditionObject(); } // 外部类传递的方法 /** * 获取独占锁持有的线程 */ final Thread getOwner() { //状态为0表示没有锁,返回空. return getState() == 0 ? null : getExclusiveOwnerThread(); } /** * 获取锁的数量 */ final int getHoldCount() { return isHeldExclusively() ? getState() : 0; } /** * 判断是否被锁 */ final boolean isLocked() { //状态不为0表示有锁 return getState() != 0; } /** * 从流重构实例(即反序列化). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); // 重置无锁状态 } }FairSync和NonFairSync分别继承了Sync类,下面来看看它们的分别实现
/** * 非公平锁 */ static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * 非公平锁的lock会无视等待队列,直接去尝试获取锁,不成功则在调用acquire()尝试获取锁 */ final void lock() { //如果AQS的状态为0,则将状态变为1,表示获得一把锁.然后设置独占锁所持有的线程为当前线程 if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } /** * 尝试获取锁 */ protected final boolean tryAcquire(int acquires) { //调用Sync的nonfairTryAcquire(args)方法 return nonfairTryAcquire(acquires); } } /** * 公平锁 */ static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; /** * 获取一把锁 */ final void lock() { acquire(1); } /** * 去尝试获取锁,获取成功则设置锁状态并返回true,否则返回false */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { //hasQueuedPredecessors()方法是查询队列中是否有比当前线程等待更长时间的线程 if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } }可以看出公平锁和非公平尝试获取锁的不同之处就体现在if(c == 0 )中
// -----非公平锁-----if(c==0){if (compareAndSetState(0, acquires)) {etExclusiveOwnerThread(current);return true;}}// -------公平锁-----if(c==0){ if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } }ReentrantLock类的其他方法:
/** * 无参构造 */public ReentrantLock() {sync = new NonfairSync();}/** * 构建公平锁或非公平锁 */public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}/** * 获取锁:如果锁没有被另一个线程占用并且立即返回,则将锁定计数设置为1 * 如果当前线程已经保持锁定,则保持计数增加1,该方法立即返回。 * 如果锁被另一个线程保持,则当前线程将被禁用以进行线程调度,并处于休眠状态,直到锁定被获取为止,此时锁定保持计数被设置为1. */public void lock() {sync.lock();}/** * 获取锁,除非当前线程中断 */public void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);}/** * 如果没有被另一个线程占用,则获取该锁,并立即返回该值.设置锁数量为1 */public boolean tryLock() {return sync.nonfairTryAcquire(1);}/** * 尝试在指定时间内获取锁 * 指定时间内没获取到返回false */public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));}/** * 释放一把锁 */public void unlock() {sync.release(1);}/** * 构建一个Condition实例 */public Condition newCondition() {return sync.newCondition();}/** * 获取线程对当前锁的持有数 */public int getHoldCount() {return sync.getHoldCount();}/** * 查询锁是否被当前线程持有 */public boolean isHeldByCurrentThread() {return sync.isHeldExclusively();}/** * 查询是否被锁 */public boolean isLocked() {return sync.isLocked();}/** *是否是公平锁 */public final boolean isFair() {return sync instanceof FairSync;}/** * 返回持有锁的线程 */protected Thread getOwner() {return sync.getOwner();}/** * 查询是否还有线程等待该锁 */public final boolean hasQueuedThreads() {return sync.hasQueuedThreads();}/** * 查询给定的线程是否在等待该锁 */public final boolean hasQueuedThread(Thread thread) {return sync.isQueued(thread);}
参考文献:
【Java并发编程实战】—–“J.U.C”:ReentrantLock之二lock方法分析
源码来自JDK1.8,注释来自自己翻译,不足自出希望指正
0 0
- 实战Java高并发程序设计之ReentrantLock(二)
- 实战Java高并发程序设计之ReentrantLock(一)
- 实战Java高并发程序设计之概念
- 实战Java高并发程序设计之Semaphoer
- 实战Java高并发程序设计之ReadWriteLock
- 实战Java高并发程序设计之CountDownLatch
- 实战Java高并发程序设计之CyclicBarrier
- 实战Java高并发程序设计之LockSupport
- 实战java高并发程序设计第之java并发基础
- java高并发程序设计总结三:JDK并发包之ReentrantLock重入锁
- 【Java并发编程实战】—–“J.U.C”:ReentrantLock之二lock方法分析
- 【Java并发编程实战】—–“J.U.C”:ReentrantLock之二lock方法分析
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之二lock方法分析
- 实战java高并发程序设计第一章读书笔记
- 实战java高并发程序设计读书笔记一
- 《实战Java高并发程序设计》读书笔记
- 《实战Java高并发程序设计》读后感
- 【备忘】Java高并发程序设计实战视频教程
- (转)Vim十大必备插件
- CSS选择器
- (转)Vim自动补全神器:YouCompleteMe
- Ubuntu:Could not get lock /var/lib/dpkg/lock
- cygwin Could not create directory '/home/Administrator/.ssh'
- 实战Java高并发程序设计之ReentrantLock(二)
- (转)使用cygwin注意事项一
- 使用cygwin注意事项二
- vim 使用、设置笔记
- (转)vim 访问系统剪贴板
- 003云数据中心基础原理笔记
- c/c++生成预编译文件
- 注意!!一定要谨慎使用c/c++原生指针
- 安卓解决listview的item嵌套多个edittext的问题