java同步器__学习笔记

参照:http://ifeve.com/introduce-abstractqueuedsynchronizer/

 

前言:

在java.util.concurrent.locks包中有很多Lock的实现类,常用的有ReentrantLock、ReadWriteLock(实现类ReentrantReadWriteLock),内部实现都依赖AbstractQueuedSynchronizer类

public abstract class AbstractQueuedSynchronizer extends
    AbstractOwnableSynchronizer implements java.io.Serializable { 
    //等待队列的头节点
    private transient volatile Node head;
    //等待队列的尾节点
    private transient volatile Node tail;
    //同步状态
    private volatile int state;
    protected final int getState() { return state;}
    protected final void setState(int newState) { state = newState;}
    ...
}

队列同步器AQS通过内置的FIFO队列来完成资源获取线程的排队工作。

volatile修饰,保证多线程之间的可见。

FIFO队列 先进先出

 

Head 节点本身不保存等待线程的信息,它通过 next 变量指向第一个保存线程等待信息的节点(Node1)。当线程被唤醒之后,会删除 Head 节点,而唤醒线程所在的节点会设置为 Head 节点(Node1 被唤醒之后,Node1会被置为 Head 节点)。

 

static final class Node {
        static final Node SHARED = new Node();
        static final Node EXCLUSIVE = null;//独占模式
        static final int CANCELLED =  1;//等待超时或中断,此节点不会竞争锁,也不会被阻塞。此节点会被移出队列,被GC回收。
        static final int SIGNAL    = -1;//表示当前节点的后继节点包含的线程需要运行,也就是unpark;
        static final int CONDITION = -2;//表示当前节点在等待condition,也就是在condition队列中;
        static final int PROPAGATE = -3;//在共享模式下,可以认为资源有多个,因此当前线程被唤醒之后,可能还有剩余的资源可以唤醒其他线程。该状态用来表明后续节点会传播唤醒的操作。需要注意的是只有头节点才可以设置为该状态
        volatile int waitStatus;//代表对应线程状态 0 表示当前节点在sync队列中,等待着获取锁。
        volatile Node prev;
        volatile Node next;
        volatile Thread thread;//入队列时的当前线程。
        Node nextWaiter;//指向下一个在某个条件上等待的节点,或者指向 SHARE 节点,表明当前处于共享模式
        ...
    }

 等待队列时FIFIO先进先出,只有前面一个节点的状态为SIGNAL时,当前节点才会被挂起。

参考:https://www.cnblogs.com/zhangjk1993/archive/2017/04/15/6715653.html

独占锁获取流程:

独占锁释放:

 

共享锁释放流程:

共享锁获取流程:

 

posted @ 2018-03-14 10:24  战斗的小白  阅读(720)  评论(0编辑  收藏  举报