AQS详解(一)-源码分析

AQS源码

添加头节点

这是场景2的类型1,多个线程竞争头节点和尾节点

public abstract class AbstractQueuedSynchronizer
    extends AbstractOwnableSynchronizer
    implements java.io.Serializable {
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;// 查询完成状态tail
            if (t == null) {  //完成状态未设置
                if (compareAndSetHead(new Node())) //添加到等待队列成功
                    tail = head;//设置完成状态tail
            } else { //变量不满足要求
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }
}

后一个节点线程等待前一个节点执行完成

这是场景1的情况,完成状态是head

等待线程
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implement java.io.Serializable {
    
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) { //查询完成状态head+结果满足要求tryAcquire
                    setHead(node); 
                    p.next = null; 
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&  //判断是否在等待队列,不在就添加到等待队列,并重新查询完成状态+结果满足要求
                    parkAndCheckInterrupt()) //在等待队列中,调用等待函数Locksupport.park挂起线程
                                             //被唤醒的时候判断是否被中断
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
    
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL) //ws==Node.SIGNAL表示在等待队列中(等待队列的第一种情况)
            return true;
        if (ws > 0) {
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);//添加到等待队列(等待队列的第一种情况)
        }
        return false;
    }
    
    private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this); //调用等待函数Locksupport.park挂起线程
        return Thread.interrupted(); //被唤醒的时候判断是否被中断,同时会清除中断标志
    }
}
工作线程
class Thread(){
    void run(){
        acquire(1);
        //todo: 业务逻辑
        release(1);
    }
}
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implement java.io.Serializable {
    
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);//设置完成标志
                    p.next = null; 
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    //todo: 业务代码
    public final boolean release(int arg) {
        if (tryRelease(arg)) {//设置结果tryRelease(设置完成标志在设置结果之前,场景1图中已经分析过原因)
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);//清空等待队列并唤醒队列中的线程
            return true;
        }
        return false;
    }
    
    private void unparkSuccessor(Node node) {
      
        int ws = node.waitStatus;
        if (ws < 0)
            compareAndSetWaitStatus(node, ws, 0); //清空等待队列

        Node s = node.next;
        if (s == null || s.waitStatus > 0) {
            s = null;
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }
        if (s != null)
            LockSupport.unpark(s.thread);//调用等待唤醒函数Locksupport.unpark唤醒线程
    }
}

线程唤醒后一个节点的线程

  1. 如果线程唤醒的后一个节点是一个正在取消的线程,为了保证取消的线程后面的节点可以被唤醒,有两种选择
    1.取消的线程负责唤醒后一个节点的线程
    2.当前线程跳过这个正在取消的线程,自己负责唤醒后一个节点的线程
    这两个线程必须保证至少有一个会去唤醒后一个节点的线程,这是场景3的情况
  2. 如果线程唤醒的后一个节点是一个没有取消的线程,自己负责唤醒后一个节点的线程

取消的线程

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implement java.io.Serializable {
    
   final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null;
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node); //取消线程
        }
    }

    private void cancelAcquire(Node node) {
        if (node == null)
            return;
        node.thread = null;//设置变量A1 thread=null

        Node pred = node.prev;
        while (pred.waitStatus > 0)
            node.prev = pred = pred.prev;
        
        Node predNext = pred.next;
        node.waitStatus = Node.CANCELLED;//设置变量A2 waitStatus=Node.CANCELLED

        if (node == tail && compareAndSetTail(node, pred)) {
            compareAndSetNext(pred, predNext, null);
        } else {
            int ws;
            if (pred != head && //判断!B1 
                ((ws = pred.waitStatus) == Node.SIGNAL ||
                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) && //判断!A2
                pred.thread != null) { //判断!A1 && !B2  这个条件是不是有点多余了?
                Node next = node.next;
                if (next != null && next.waitStatus <= 0)
                    compareAndSetNext(pred, predNext, next);
            } else {
                unparkSuccessor(node);//公共代码LockSupport.unpark
            }

            node.next = node;
        }
    }
}
    

正常执行的线程

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implement java.io.Serializable {
    
   final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node); //设置头节点
                    p.next = null;
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
   }

   private void setHead(Node node) {
        head = node;       //设置B1 pred=head
        node.thread = null;//设置B2 thread==null
        node.prev = null;
   }

   //todo: 业务代码
    
   public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }
    
    private void unparkSuccessor(Node node) {
        int ws = node.waitStatus;
        if (ws < 0)
            compareAndSetWaitStatus(node, ws, 0);

        Node s = node.next;
        if (s == null || s.waitStatus > 0) {
            s = null;
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0) //判断变量A2 waitStatus!=Node.CANCELLED
                    s = t;
        }
        if (s != null)
            LockSupport.unpark(s.thread);//公共代码LockSupport.unpark
    }
}
  1. 因为取消的线程前面可能是取消的线程也可能是正常执行的线程,所以既要判断前面是取消的线程的条件,也要判断前面是正常的线程的条件
  2. 因为正常执行的线程只需要和后面取消的线程有一个执行unpark就行,而不用关心后面也是正常线程的情况,所以只需要判断后面是取消的线程的情况
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值