Java多线程之AbstractQueuedSynchronizer

2020年5月7日 《Java并发编程之美》第六章第二小节


2018年03月31日 再理解AQS队列同步器
利用AQS实现独占锁:https://blog.csdn.net/kevin_king1992/article/details/79813078
Java并发之AQS详解:https://my.oschina.net/wugong/blog/1784946


2017年06月18日

参考:JDK 1.6.0 API 中文版
参考:JDK 1.8.0_121
参考:http://www.jianshu.com/p/ac0fb814e1a3
参考:http://www.jianshu.com/p/791981de7579
感谢作者。

AQS类简介

public abstract class AbstractQueuedSynchronizer 
extends AbstractOwnableSynchronizer implements java.io.Serializable { 
}

由上面可以看出AbstractQueuedSynchronizer是一个继承了AbstractOwnableSynchronizer的抽象类。
那么AbstractOwnableSynchronizer又是什么呢?AbstractOwnableSynchronizer是可以由线程以独占方式拥有的同步器。
AbstractOwnableSynchronizer源码如下:

public abstract class AbstractOwnableSynchronizer implements java.io.Serializable { 
	//供子类使用的空构造方法 
	protected AbstractOwnableSynchronizer() { } 
	private transient Thread exclusiveOwnerThread; 
	//设置当前拥有独占访问的线程。
	protected final void setExclusiveOwnerThread(Thread thread){ 
	    exclusiveOwnerThread = thread; 
	} 
	//返回由 setExclusiveOwnerThread 最后设置的线程;如果从未设置,则返回 null。
	protected final Thread getExclusiveOwnerThread() { return exclusiveOwnerThread; }
}

关于transient文章: http://www.cnblogs.com/liuling/archive/2013/05/05/transient.html

AQS同步队列数据结构

在AbstractQueuedSynchronizer源码中,有一个静态的内部类Node,

AQS通过内置的FIFO同步队列来完成资源获取线程的排队工作,如果当前线程获取同步状态失败(锁)时,AQS则会将当前线程以及等待状态等信息构造成一个节点(Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,则会把节点中的线程唤醒,使其再次尝试获取同步状态。(引自:http://www.jianshu.com/p/ac0fb814e1a3)

static final class Node {
    /** 共享node */
    static final Node SHARED = new Node();
    /** 独享node */
    static final Node EXCLUSIVE = null;

	//以下为waitStatus的状态常量表示
    /** 取消状态 */
    static final int CANCELLED =  1;
    /** 通知状态 */
    static final int SIGNAL    = -1;
    /** 条件等待状态 */
    static final int CONDITION = -2;
    /** 传播状态 */
    static final int PROPAGATE = -3;
    volatile int waitStatus;
    volatile Node prev;
    volatile Node next;
    volatile Thread thread;
    Node nextWaiter;
    //判断是否是共享锁。
    final boolean isShared() {
        return nextWaiter == SHARED;
    }

    //返回前驱节点,没有则抛出异常
    final Node predecessor() throws NullPointerException {
        Node p = prev;
        if (p == null)
            throw new NullPointerException();
        else
            return p;
    }

    Node() { // 被用于创建初始的头结点或共享创建者
    }

    Node(Thread thread, Node mode) { // 被用于添加等待者
        this.nextWaiter = mode;
        this.thread = thread;
    }

    Node(Thread thread, int waitStatus) { //被用于 条件Condition
        this.waitStatus = waitStatus;
        this.thread = thread;
    }
}

头结点,懒加载:
private transient volatile Node head;
尾结点,同样也是懒加载,
private transient volatile Node tail;
同步状态:
private volatile int state;

AQS中维持的state变量

当state>0的时候获取锁,当state=0的时候锁空闲。
通过 getState()setState(int newState)、compareAndSetState(int expect, int update) 进行state状态变量的获取和设置。

AQS队列的维护

入队操作:

private Node enq(final Node node) {
    for (;;) {
        Node t = tail;
        if (t == null) { // Must initialize
            if (compareAndSetHead(new Node()))
                tail = head;
        } else {
            node.prev = t;
            if (compareAndSetTail(t, node)) {
                t.next = node;
                return t;
            }
        }
    }
}

ASQ方法简介

AQS主要提供了如下一些方法:

  • getState():返回同步状态的当前值;
  • setState(int newState):设置当前同步状态;
  • compareAndSetState(int expect, int
  • update):使用CAS设置当前状态,该方法能够保证状态设置的原子性; tryAcquire(int
  • arg):独占式获取同步状态,获取同步状态成功后,其他线程需要等待该线程释放同步状态才能获取同步状态; tryRelease(int
  • arg):独占式释放同步状态; tryAcquireShared(int
  • arg):共享式获取同步状态,返回值大于等于0则表示获取成功,否则获取失败;
  • tryReleaseShared(int arg):共享式释放同步状态;
  • isHeldExclusively():当前同步器是否在独占式模式下被线程占用,一般该方法表示是否被当前线程所独占;
  • acquire(int arg):独占式获取同步状态,如果当前线程获取同步状态成功,则由该方法返回,否则,将会进入同步队列等待,该方法将会调用可重写的tryAcquire(int
    arg)方法;
  • acquireInterruptibly(int arg):与acquire(int arg)相同,但是该方法响应中断,当前线程为获取到同步状态而进入到同步队列中,如果当前线程被中断,则该方法会抛出InterruptedException异常并返回;
  • tryAcquireNanos(int arg,long nanos):超时获取同步状态,如果当前线程在nanos时间内没有获取到同步状态,那么将会返回false,已经获取则返回true;
  • acquireShared(int arg):共享式获取同步状态,如果当前线程未获取到同步状态,将会进入同步队列等待,与独占式的主要区别是在同一时刻可以有多个线程获取到同步状态;
  • acquireSharedInterruptibly(int arg):共享式获取同步状态,响应中断;
  • tryAcquireSharedNanos(int arg, long nanosTimeout):共享式获取同步状态,增加超时限制;
  • release(int arg):独占式释放同步状态,该方法会在释放同步状态之后,将同步队列中第一个节点包含的线程唤醒;
  • releaseShared(int arg):共享式释放同步状态;

摘自:http://www.jianshu.com/p/ac0fb814e1a3

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值