文章40 | 阅读 10640 | 点赞0
AbstractQueuedSynchronizer简化后的大致结构
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
private static final long serialVersionUID = 7373984972572414691L; // 序列化版本号
static final int WAITING = 1; // 常量1,表示线程等待
static final int CANCELLED = 0x80000000; // 常量负数,表示取消等待
static final int COND = 2; // 常量2
private volatile int state; // 等待线程的个数
private transient volatile Node head; // AQS队列的头
private transient volatile Node tail; // AQS队列的尾
private static final Unsafe U = Unsafe.getUnsafe(); //用的都是最底层的操作,里面有很多关于cas操作的native方法
private static final long HEAD = U.objectFieldOffset(AbstractQueuedSynchronizer.class, "head"); // 使用cas对内存操作head的偏移量
private static final long TAIL = U.objectFieldOffset(AbstractQueuedSynchronizer.class, "tail"); // 使用cas对内存操作tail的偏移量
private static final long STATE = U.objectFieldOffset(AbstractQueuedSynchronizer.class, "state"); // 使用cas对内存操作state的偏移量
static {
java.lang.Class<?> ensureLoaded = LockSupport.class; // LockSupport实例,确保LockSupport类被初始化
}
/** * CLH Nodes */
abstract static class Node{...}
// 排他锁队列
static final class ExclusiveNode extends Node{...}
// 共享锁队列
static final class SharedNode extends Node{...}
//
static final class ConditionNode extends Node implements ForkJoinPool.ManagedBlocker{...}
//
public class ConditionObject implements Condition, java.io.Serializable{...}
/** * AbstractQueuedSynchronizer定义的一些方法 */
...
}
ReentrantLock简化后大致的结构
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L; // 序列化版本号
private final Sync sync; // 同步器,在实例化时会赋值为非公平锁/公平锁的其中一个
/** * Sync是公平锁和非公平锁的父类 */
abstract static class Sync extends AbstractQueuedSynchronizer{...}
/** * 非公平锁 */
static final class NonfairSync extends Sync{...}
/** * 公平锁 */
static final class FairSync extends Sync{...}
/** * 默认创建一个非公平锁 */
public ReentrantLock() {
sync = new NonfairSync();
}
/** * true则是公平锁,false则是非公平锁 */
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
/** * ReentrantLock定义的一些方法 */
...
}
之所以将AQS和ReentrantLock简化成上面的代码,目的是方便回忆源码。
好比素描,先画轮廓,再细化。
AQS队列是如何形成的?
AQS队列的数据结构是什么?
ReentrantLock是怎么锁住线程的?
ReentrantLock如何如何防止死锁?
以下面代码为例
如果将第一个线程中finelly中的解锁注释掉,导致线程A一直在占用锁,线程B中不会输出B:这是一段加锁代码段
在这过程中,到底做了哪些事情呢?
public class ReentrantLockTest {
static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
new Thread(()->{
try {
lock.lock();
System.out.println("A:这是一段加锁代码段");
} finally {
//lock.unlock();
}
},"A").start();
new Thread(()->{
try {
lock.lock();
System.out.println("B:这是一段加锁代码段");
} finally {
lock.unlock();
}
},"B").start();
}
}
如果想要知道具体做了哪些事情则需要掌握AQS的源码,这样才能真正的掌握ReentrantLock的原理。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://yumbo.blog.csdn.net/article/details/109501486
内容来源于网络,如有侵权,请联系作者删除!