Jdk源码分析

文章40 |   阅读 10629 |   点赞0

来源:https://yumbo.blog.csdn.net/category_10384063.html

ReentrantLock和AbstractQueuedSynchronizer的整体结构

x33g5p2x  于2021-12-18 转载在 其他  
字(2.6k)|赞(0)|评价(0)|浏览(253)
去掉定义的方法,AQS和可重入锁留下了哪些结构?

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的原理。

文章推荐:

以ReentrantLock的非公平锁为例深入解读AQS源码

相关文章