深入浅出java并发编程(AbstractQueuedSynchronizer)(AQS)

2023-11-03

前言

Abstract抽象的、Ownable拥有、Synchronizer同步器、Queued队列。
AbstractOwnableSynchronizer简称为AOS。
AbstractQueuedSynchronizer简称为AQS。

AbstractOwnableSynchronizer(AOS)

public abstract class AbstractOwnableSynchronizer implements java.io.Serializable {    
    
    protected AbstractOwnableSynchronizer() { }
    //私有的不会被序列化的独占thread
    private transient Thread exclusiveOwnerThread;
    //set
    protected final void setExclusiveOwnerThread(Thread thread) {
        exclusiveOwnerThread = thread;
    }
    //get
    protected final Thread getExclusiveOwnerThread() {
        return exclusiveOwnerThread;
    }
}

由于AOS是一个抽象类不能直接实例化,我们定义一个子类实例化

public class AosClient extends AbstractOwnableSynchronizer {
    public static void main(String[] args) {
        AosClient client = new AosClient();
        client.setExclusiveOwnerThread(Thread.currentThread());
        Thread exclusiveOwnerThread = client.getExclusiveOwnerThread();
        System.out.println(exclusiveOwnerThread);
    }
}

输出

Thread[main,5,main]

AOS比较简单,只有一个参数线程,可以通过get和set来设置这个线程。

AbstractQueuedSynchronizer(AQS)

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

AQS继承了AOS,又因为本身是一个抽象类无法直接进行实例化。

实例化

由于AQS也是一个抽象类不能直接实例化,所以我们定义一个子类实例化

public class AqsClient extends AbstractQueuedSynchronizer {
    public static void main(String[] args) {
        AqsClient client = new AqsClient();
    }
}

不同包子类可以直接调用父类中的public和protected方法。

AQS 源码注释

Provides a framework for implementing blocking locks and related synchronizers (semaphores, events, etc) that rely on first-in-first-out (FIFO) wait queues.

AQS可以认为是一个framework 框架,实现阻塞锁和相关同步器。依赖 FIFO 等待队列。

Subclasses should be defined as non-public internal helper classes that are used to implement the synchronization properties of their enclosing class.

子类应该被定义为non-public internal helper(非公共内部)类,用于在实现同步属性。

AQS子类

//ReentrantLock
abstract static class Sync extends AbstractQueuedSynchronizer
//ReentrantReadWriteLock
abstract static class Sync extends AbstractQueuedSynchronizer
//CountDownLatch
private static final class Sync extends AbstractQueuedSynchronizer 
//Semaphore
abstract static class Sync extends AbstractQueuedSynchronizer 

这些类都是通过定义静态内部类的形式类使用AQS。在Sync的内部重写tryAcquire、tryRelease等方法,这些方法都有一个特点,那就是在AQS中没有实现,只会抛出一个UnsupportedOperationException,例如tryRelease

    protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
    }

例如CountDownLatch重写的tryAcquireShared

        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

然后在另一个方法await中调用

    public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

tryAcquireSharedNanos中调用了tryAcquireShared(arg),如果方法没有实现就会抛出异常。

自定义 Sync

我们来定义一个Sync,模仿CountDownLatch

    private static final class Sync extends AbstractQueuedSynchronizer {
        Sync(int count) {
            logger.info("Sync 初始化...");
            setState(count);
        }     

        int getCount() {
            return getState();
        }
    }

在Sync的内部根据权限设计,可以访问protected和public级别的方法。而在Sync的外部我们只关心public方法。

AQS public方法

如下图,首先我们来整体感受一下所有的public方法
在这里插入图片描述
idea中小绿锁代表public,左上角的白色代表final。也就是所有的public均为final。

acquire

以独占模式获取锁,并且忽略中断,实现至少调用一次tryAcquire,成功后返回,否则线程将会排队,可能重复阻塞或者取消阻塞知道调用tryAcquire成功,此方法可以用来实现加锁。

    public final void acquire(int arg) {
        if (!tryAcquire(arg))
            acquire(null, arg, false, false, false, 0L);
    }

tryAcquire

        protected final boolean tryAcquire(int acquires) {
            if (getState() == 0 && compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

acquireInterruptibly

由于acquire不支持中断,所以该模式支持了响应中断

    public final void acquireInterruptibly(int arg)
        throws InterruptedException {
        if (Thread.interrupted() ||
            (!tryAcquire(arg) && acquire(null, arg, false, true, false, 0L) < 0))
            throw new InterruptedException();
    }

acquireShared

类似于acquire,不同是以共享模式获取锁。

    public final void acquireShared(int arg) {
        if (tryAcquireShared(arg) < 0)
            acquire(null, arg, true, false, false, 0L);
    }

参数对比第一个是acquire,第二个是acquireShared,两者只有第三个参数也就是boolean shared 发生变化。

 acquire(null, arg, false, false, false, 0L);
 acquire(null, arg, true, false, false, 0L);

acquireSharedInterruptibly

类似于第二个方法acquireInterruptibly,区别是一个是独占模式,这个是共享模式。

    public final void acquireSharedInterruptibly(int arg)
        throws InterruptedException {
        if (Thread.interrupted() ||
            (tryAcquireShared(arg) < 0 &&
             acquire(null, arg, true, true, false, 0L) < 0))
            throw new InterruptedException();
    }

getWaitingThreads

获取等待线程并且返回一个集合

    public final Collection<Thread> getWaitingThreads(ConditionObject condition) {
   		//判断条件所属
        if (!owns(condition))
            throw new IllegalArgumentException("Not owner");
        return condition.getWaitingThreads();
    }

实现中调用了 condition.getWaitingThreads() 这个方法。

getWaitQueueLength

获取等待队列长度

    public final int getWaitQueueLength(ConditionObject condition) {
        if (!owns(condition))
            throw new IllegalArgumentException("Not owner");
        return condition.getWaitQueueLength();
    }

hasContended

判断 head 是否为空

    public final boolean hasContended() {
        return head != null;
    }

hasQueuedPredecessors

    public final boolean hasQueuedPredecessors() {
        Thread first = null; Node h, s;
        if ((h = head) != null && ((s = h.next) == null ||
                                   (first = s.waiter) == null ||
                                   s.prev == null))
            first = getFirstQueuedThread(); // retry via getFirstQueuedThread
        return first != null && first != Thread.currentThread();
    }

hasQueuedThreads

    public final boolean hasQueuedThreads() {
        for (Node p = tail, h = head; p != h && p != null; p = p.prev)
            if (p.status >= 0)
                return true;
        return false;
    }

hasWaiters

    public final boolean hasWaiters(ConditionObject condition) {
        if (!owns(condition))
            throw new IllegalArgumentException("Not owner");
        return condition.hasWaiters();
    }

isQueued

判断给定线程是否在队列中

    public final boolean isQueued(Thread thread) {
        if (thread == null)
            throw new NullPointerException();
        for (Node p = tail; p != null; p = p.prev)
            if (p.waiter == thread)
                return true;
        return false;
    }

owns

    public final boolean owns(ConditionObject condition) {
        return condition.isOwnedBy(this);
    }

release

    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            signalNext(head);
            return true;
        }
        return false;
    }

releaseShared

    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            signalNext(head);
            return true;
        }
        return false;
    }

tryAcquireNanos

    public final boolean tryAcquireNanos(int arg, long nanosTimeout)
        throws InterruptedException {
        if (!Thread.interrupted()) {
            if (tryAcquire(arg))
                return true;
            if (nanosTimeout <= 0L)
                return false;
            int stat = acquire(null, arg, false, true, true,
                               System.nanoTime() + nanosTimeout);
            if (stat > 0)
                return true;
            if (stat == 0)
                return false;
        }
        throw new InterruptedException();
    }

tryAcquireSharedNanos

    public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (!Thread.interrupted()) {
            if (tryAcquireShared(arg) >= 0)
                return true;
            if (nanosTimeout <= 0L)
                return false;
            int stat = acquire(null, arg, true, true, true,
                               System.nanoTime() + nanosTimeout);
            if (stat > 0)
                return true;
            if (stat == 0)
                return false;
        }
        throw new InterruptedException();
    }

AQS protected方法

在这里插入图片描述
分为 final 和 非 final 方法,其中 3,5,6,7,8方法可以由子类进行一个重写。

final

compareAndSetState

    protected final boolean compareAndSetState(int expect, int update) {
        return U.compareAndSetInt(this, STATE, expect, update);
    }

getState

    protected final int getState() {
        return state;
    }

setState

    protected final void setState(int newState) {
        state = newState;
    }

非final(可重写)

tryAcquire

    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }

tryAcquireShared

    protected int tryAcquireShared(int arg) {
        throw new UnsupportedOperationException();
    }

tryRelease

    protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
    }

tryReleaseShared

    protected boolean tryReleaseShared(int arg) {
        throw new UnsupportedOperationException();
    }

isHeldExclusively

    protected boolean isHeldExclusively() {
        throw new UnsupportedOperationException();
    }

AQS default方法

在这里插入图片描述
图标显示为一个圆圈的访问级别为default默认隔离接别(又称包隔离级别)。根据图标可以看出这里的方法不是final就是static的都是可以用但是不能改的形式。

acquireQueued

    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; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

apparentlyFirstQueuedIsExclusive

    final boolean apparentlyFirstQueuedIsExclusive() {
        Node h, s;
        return (h = head) != null &&
            (s = h.next)  != null &&
            !s.isShared()         &&
            s.thread != null;
    }

fullyRelease

    final int fullyRelease(Node node) {
        boolean failed = true;
        try {
            int savedState = getState();
            if (release(savedState)) {
                failed = false;
                return savedState;
            } else {
                throw new IllegalMonitorStateException();
            }
        } finally {
            if (failed)
                node.waitStatus = Node.CANCELLED;
        }
    }

isOnSyncQueue

    final boolean isOnSyncQueue(Node node) {
        if (node.waitStatus == Node.CONDITION || node.prev == null)
            return false;
        if (node.next != null) // If has successor, it must be on queue
            return true;
            
        return findNodeFromTail(node);
    }

selfInterrupt

    static void selfInterrupt() {
        Thread.currentThread().interrupt();
    }

transferAfterCancelledWait

    final boolean transferAfterCancelledWait(Node node) {
        if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
            enq(node);
            return true;
        }
        while (!isOnSyncQueue(node))
            Thread.yield();
        return false;
    }

transferForSignal

    final boolean transferForSignal(Node node) {
     
        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
            return false;
   
        Node p = enq(node);
        int ws = p.waitStatus;
        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
            LockSupport.unpark(node.thread);
        return true;
    }

AQS private方法

在这里插入图片描述

addWaiter

    private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }

cancelAcquire

    private int cancelAcquire(Node node, boolean interrupted,
                              boolean interruptible) {
        if (node != null) {
            node.waiter = null;
            node.status = CANCELLED;
            if (node.prev != null)
                cleanQueue();
        }
        if (interrupted) {
            if (interruptible)
                return CANCELLED;
            else
                Thread.currentThread().interrupt();
        }
        return 0;
    }

casTail

    private boolean casTail(Node c, Node v) {
        return U.compareAndSetReference(this, TAIL, c, v);
    }

cleanQueue

    private void cleanQueue() {
        for (;;) {                               // restart point
            for (Node q = tail, s = null, p, n;;) { // (p, q, s) triples
                if (q == null || (p = q.prev) == null)
                    return;                      // end of list
                if (s == null ? tail != q : (s.prev != q || s.status < 0))
                    break;                       // inconsistent
                if (q.status < 0) {              // cancelled
                    if ((s == null ? casTail(q, p) : s.casPrev(q, p)) &&
                        q.prev == p) {
                        p.casNext(q, s);         // OK if fails
                        if (p.prev == null)
                            signalNext(p);
                    }
                    break;
                }
                if ((n = p.next) != q) {         // help finish
                    if (n != null && q.prev == p) {
                        p.casNext(n, q);
                        if (p.prev == null)
                            signalNext(p);
                    }
                    break;
                }
                s = q;
                q = q.prev;
            }
        }
    }

signalNext

    private static void signalNext(Node h) {
        Node s;
        if (h != null && (s = h.next) != null && s.status != 0) {
            s.getAndUnsetStatus(WAITING);
            LockSupport.unpark(s.waiter);
        }
    }

signalNextIfShared

    private static void signalNextIfShared(Node h) {
        Node s;
        if (h != null && (s = h.next) != null &&
            (s instanceof SharedNode) && s.status != 0) {
            s.getAndUnsetStatus(WAITING);
            LockSupport.unpark(s.waiter);
        }
    }

tryInitializeHead

    private void tryInitializeHead() {
        Node h = new ExclusiveNode();
        if (U.compareAndSetReference(this, HEAD, null, h))
            tail = h;
    }

AQS内部类

Node

Wait queue node class.
The wait queue is a variant of a “CLH” (Craig, Landin, and Hagersten) lock queue.

    static final class Node {
        
        static final Node SHARED = new Node();

        static final Node EXCLUSIVE = null;

        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) { 
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

ConditionObject

    public class ConditionObject implements Condition, java.io.Serializable {}

Condition

用于线程的等待和唤醒。

public interface Condition {
    //等待可中断
    void await() throws InterruptedException;
    //给定时间等待可中断
    boolean await(long time, TimeUnit unit) throws InterruptedException;
    // or the specified waiting time elapses. 经过等待指定时间
    long awaitNanos(long nanosTimeout) throws InterruptedException;
   	//不响应中断
    void awaitUninterruptibly();
    //等待直到
    boolean awaitUntil(Date deadline) throws InterruptedException;
    //随机唤醒
    void signal();
    //唤醒全部
    void signalAll();
}

ConditionObject构造函数

        public ConditionObject() { }

ConditionObject字段

        private static final long serialVersionUID = 1173984872572414699L;
        //第一个节点
        private transient ConditionNode firstWaiter;
        //最后一个节点
        private transient ConditionNode lastWaiter;

ConditionObject属性

		//获取等待队列长度
        protected final int getWaitQueueLength() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            int n = 0;
            for (ConditionNode w = firstWaiter; w != null; w = w.nextWaiter) {
                if ((w.status & COND) != 0)
                    ++n;
            }
            return n;
        }
		//获取等待线程
        protected final Collection<Thread> getWaitingThreads() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            ArrayList<Thread> list = new ArrayList<>();
            for (ConditionNode w = firstWaiter; w != null; w = w.nextWaiter) {
                if ((w.status & COND) != 0) {
                    Thread t = w.waiter;
                    if (t != null)
                        list.add(t);
                }
            }
            return list;
        }

ConditionObject方法

ConditionObject.hasWaiters

判断队列有无等待线程

        protected final boolean hasWaiters() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            for (ConditionNode w = firstWaiter; w != null; w = w.nextWaiter) {
                if ((w.status & COND) != 0)
                    return true;
            }
            return false;
        }
ConditionObject.isOwnedBy

如果此条件是由给定的同步对象创建的,则返回true。

        final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
            return sync == AbstractQueuedSynchronizer.this;
        }
ConditionObject.canReacquire

如果最初放置在条件队列中的节点现在可以在同步队列中重新获取,则返回true。

        private boolean canReacquire(ConditionNode node) {
            return node != null && node.prev != null && isEnqueued(node);
        }
ConditionObject.doSignal

移除一个或所有等待者并将其转移到同步队列。

        private void doSignal(ConditionNode first, boolean all) {
            while (first != null) {
                ConditionNode next = first.nextWaiter;
                if ((firstWaiter = next) == null)
                    lastWaiter = null;
                if ((first.getAndUnsetStatus(COND) & COND) != 0) {
                    enqueue(first);
                    if (!all)
                        break;
                }
                first = next;
            }
        }
ConditionObject.enableWait

将节点添加到条件列表并释放锁。

        private int enableWait(ConditionNode node) {
            if (isHeldExclusively()) {
                node.waiter = Thread.currentThread();
                node.setStatusRelaxed(COND | WAITING);
                ConditionNode last = lastWaiter;
                if (last == null)
                    firstWaiter = node;
                else
                    last.nextWaiter = node;
                lastWaiter = node;
                int savedState = getState();
                if (release(savedState))
                    return savedState;
            }
            node.status = CANCELLED; // lock not held or inconsistent
            throw new IllegalMonitorStateException();
        }
ConditionObject.unlinkCancelledWaiters

从条件队列中取消给定节点和其他非等待节点的链接,除非已取消链接。

        private void unlinkCancelledWaiters(ConditionNode node) {
            if (node == null || node.nextWaiter != null || node == lastWaiter) {
                ConditionNode w = firstWaiter, trail = null;
                while (w != null) {
                    ConditionNode next = w.nextWaiter;
                    if ((w.status & COND) == 0) {
                        w.nextWaiter = null;
                        if (trail == null)
                            firstWaiter = next;
                        else
                            trail.nextWaiter = next;
                        if (next == null)
                            lastWaiter = trail;
                    } else
                        trail = w;
                    w = next;
                }
            }
        }

AQS字段


    static final int WAITING   = 1;          // must be 1
    static final int CANCELLED = 0x80000000; // must be negative
    static final int COND      = 2;          // in a condition wait
    //
    private transient volatile Node head;     
    private transient volatile Node tail;
     // Unsafe
    private static final Unsafe U = Unsafe.getUnsafe();
    
    private static final long STATE
        = U.objectFieldOffset(AbstractQueuedSynchronizer.class, "state");
        
    private static final long HEAD
        = U.objectFieldOffset(AbstractQueuedSynchronizer.class, "head");
        
    private static final long TAIL
        = U.objectFieldOffset(AbstractQueuedSynchronizer.class, "tail");
    //序列化id
    private static final long serialVersionUID = 7373984972572414691L;

AQS属性

state

    private volatile int state;
    
    protected final void setState(int newState) {
        state = newState;
    }
    
     protected final int getState() {
        return state;
    }

isHeldExclusively

    protected boolean isHeldExclusively() {
        throw new UnsupportedOperationException();
    }

getSharedQueuedThreads

    public final Collection<Thread> getSharedQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<>();
        for (Node p = tail; p != null; p = p.prev) {
            if (p instanceof SharedNode) {
                Thread t = p.waiter;
                if (t != null)
                    list.add(t);
            }
        }
        return list;
    }

getQueueLength

    public final int getQueueLength() {
        int n = 0;
        for (Node p = tail; p != null; p = p.prev) {
            if (p.waiter != null)
                ++n;
        }
        return n;
    }

getQueuedThreads

获取队列线程并返回一个集合

    public final Collection<Thread> getQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<>();
        for (Node p = tail; p != null; p = p.prev) {
            Thread t = p.waiter;
            if (t != null)
                list.add(t);
        }
        return list;
    }

getFirstQueuedThread

获取队列第一个线程

    public final Thread getFirstQueuedThread() {
        Thread first = null, w; Node h, s;
        if ((h = head) != null && ((s = h.next) == null ||
                                   (first = s.waiter) == null ||
                                   s.prev == null)) {
            // 
            for (Node p = tail, q; p != null && (q = p.prev) != null; p = q)
                if ((w = p.waiter) != null)
                    first = w;
        }
        return first;
    }

getExclusiveQueuedThreads

获取独占队列线程

    public final Collection<Thread> getExclusiveQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<>();
        for (Node p = tail; p != null; p = p.prev) {
        	//如果节点不是共享节点
            if (!(p instanceof SharedNode)) {
                Thread t = p.waiter;
                if (t != null)
                    list.add(t);
            }
        }
        return list;
    }

AQS 子类

在这里插入图片描述
juc包下主要的类有CountDownLatch、ThreadPoolExecutor、ReentrantReadWriteLock、ReentrantLock等类。

AQS对于LockSupport的使用

LockSupport.unpark

private void unparkSuccessor(Node node) {
            LockSupport.unpark(s.thread);
}
final boolean transferForSignal(Node node) {
            LockSupport.unpark(node.thread);
}

LockSupport.parkXX相关方法

private void unparkSuccessor(Node node)
private final boolean parkAndCheckInterrupt()
private boolean doAcquireNanos(int arg, long nanosTimeout)
private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
final boolean transferForSignal(Node node)
public final void awaitUninterruptibly()
public final void await()
public final long awaitNanos(long nanosTimeout)
public final boolean awaitUntil(Date deadline)
public final boolean await(long time, TimeUnit unit)

AQS对于Unsafe的使用

搜索 Unsafe. 有11处用法。

1个protected 方法

    protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

1个获得unsafe实例

    private static final Unsafe unsafe = Unsafe.getUnsafe();

5个使用unsafe获得字段偏移objectFieldOffset

    static {
        try {
            stateOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
            headOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
            tailOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
            waitStatusOffset = unsafe.objectFieldOffset
                (Node.class.getDeclaredField("waitStatus"));
            nextOffset = unsafe.objectFieldOffset
                (Node.class.getDeclaredField("next"));

        } catch (Exception ex) { throw new Error(ex); }
    }

4个私有CAS方法

    private final boolean compareAndSetHead(Node update) {
        return unsafe.compareAndSwapObject(this, headOffset, null, update);
    }


    private final boolean compareAndSetTail(Node expect, Node update) {
        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
    }

 
    private static final boolean compareAndSetWaitStatus(Node node,
                                                         int expect,
                                                         int update) {
        return unsafe.compareAndSwapInt(node, waitStatusOffset,
                                        expect, update);
    }

    private static final boolean compareAndSetNext(Node node,
                                                   Node expect,
                                                   Node update) {
        return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入浅出java并发编程(AbstractQueuedSynchronizer)(AQS) 的相关文章

  • 有没有办法在 java 桌面应用程序上体验 Windows 8 Metro 的外观和感觉?

    正如标题中所述 我真的很难找到这个问题的好答案 我目前正在开发一个仅桌面应用程序 根本没有 CSS 或任何互联网部分 我希望它看起来像 Windows 8 的 Metro 外观 我不是在谈论布局 而是在谈论外观和感觉 我特别喜欢方形而不是圆
  • Hibernate 4 字节码增强不适用于脏检查优化

    我正在使用 Hibernate 4 3 6 并且我使用了最新的Maven 字节码增强 http vladmihalcea com hibernate 4 bytecode enhancement 使所有实体提高自我肮脏意识 我添加了mave
  • 从 BroadcastReceiver 获取方法来更新 UI

    我正在尝试根据变量的变化更新用户界面BroadcastReceiver 因此 我需要调用一个扩展类的方法 以获取我提到的变量 BroadcastReceiver in MainActivity取决于但我无法以任何方式获得真正的返回值 扩展的
  • 如何抑制 Cucumber/Junit 断言堆栈跟踪

    我有一个黄瓜场景 该步骤使用assertEquals 我的结果报告显示了对最终用户不友好的堆栈跟踪 我怎样才能抑制它 Scenario Add two numbers Given I have two inputs 3 and 2 When
  • ListView:防止视图回收

    我有一个使用回收视图的 ListView 我试图阻止视图被回收 所以我使用 setHasTransientState android support v4 view ViewCompatJB setHasTransientState Vie
  • APNS(Apple 推送通知服务器)的反馈服务

    我们正在使用Java作为推送通知提供商APNS I我能够将消息发送到APNS但我不知道如何获得该消息的反馈 请帮忙 反馈服务具有类似于用于发送推送通知的接口的二进制接口 您可以通过以下方式访问生产反馈服务feedback push appl
  • 按位运算符简单地翻转整数中的所有位?

    我必须翻转整数的二进制表示形式中的所有位 鉴于 10101 输出应该是 01010 当与整数一起使用时 完成此操作的按位运算符是什么 例如 如果我正在编写类似的方法int flipBits int n 什么会进入身体 我只需要翻转数字中已经
  • 如何停止使用扫描仪从标准输入读取多行?

    我正在做一个 JAVA 作业 应该处理多行输入 指令显示 输入是从标准输入读取的 给出了示例输入的示例 one 1 two 2 three 3 我不明白上面的示例输入 从标准输入读取 是什么意思 这是我编写的一个测试程序 它可以消除我的困惑
  • 限制 JPQL 中的结果数量

    如何限制从数据库检索结果的数量 select e from Entity e I need only 10 results for instance 您可以尝试像这样给出 10 个要显式获取的结果 entityManager createQ
  • 使用java在网页中进行字符编码

    如何使用java找出网页中的字符编码类型 打开与 URL 的连接 使用URL openConnection http download oracle com javase 6 docs api java net URL html openC
  • 开发人员实际上是否使用 vim 在 Windows 操作系统上编写代码(Java)? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 默认情况下,JSF 生成不可用的 ID,这些 ID 与 Web 标准的 CSS 部分不兼容

    活跃的 JSF 或 Primefaces 用户能否解释一下为什么默认情况下会发生这种情况 为什么没有人对此采取任何措施
  • 单元测试、集成测试还是设计中的问题?

    我编写了我的第一个单元测试 我认为它过于依赖其他模块 我不确定是否是因为 这是一个复杂的测试 我实际上已经编写了集成测试或 我的设计有问题 我首先要说的是 虽然我有大约 4 年的开发经验 但我从未学过 也没有人教过自动化测试 我刚刚使用 H
  • Java 常量枚举[重复]

    这个问题在这里已经有答案了 可能的重复 理解 Java 中的枚举 https stackoverflow com questions 1419835 understanding enums in java 为什么我们应该使用枚举而不是 Ja
  • 在片段之间切换时底部导航栏会向下推

    在我的活动中 我有一个底部导航栏和框架布局来显示片段 一切正常 但问题是当我开始按顺序从 1 4 移动时 底部导航栏保持在其位置 但当我突然从 4 跳到2 然后底部导航栏就会超出屏幕 当再次单击同一项目时 它就会回到正常位置 该视频将清楚地
  • 应用程序中空指针异常[重复]

    这个问题在这里已经有答案了 我正在尝试在我的应用程序中实施应用程序内计费 我写了这段代码 public class Settings extends PreferenceFragment ServiceConnection mService
  • 从特定 JAR 文件读取资源(文件的重复路径)

    假设您有 jar1 和artifactId 动物园 jar2 和artifactId 动物 两个 jar 都有一个具有相同路径的资源文件 例如 animals animal txt 有什么方法可以从特定的 jar 中读取该文件吗 使用 ge
  • 线程上下文类加载器和普通类加载器的区别

    线程的上下文类加载器和普通类加载器有什么区别 也就是说 如果Thread currentThread getContextClassLoader and getClass getClassLoader 返回不同的类加载器对象 将使用哪一个
  • 乔达时间中两个日期之间的天数

    如何找到两次之间的天数差异乔达时间 http www joda org joda time DateTime http www joda org joda time apidocs org joda time DateTime html实例
  • AES 密钥是随机的吗?

    AES 密钥可以通过此代码生成 KeyGenerator kgen KeyGenerator getInstance AES kgen init 128 but 如果我有一个 非常可靠 的生成随机数的方法 我可以这样使用它吗 SecureR

随机推荐

  • Content-Type

    要学习content type 必须事先知道它到底是什么 是干什么用的 HTTP协议 RFC2616 采用了请求 响应模型 客户端向服务器发送一个请求 请求头包含请求的方法 URI 协议版本 以及包含请求修饰符 客户 信息和内容的类似于MI
  • SQL综合案例之电商漏斗转化分析,pv,uv及

    漏斗模型示例 不同的业务场景有不同的业务路径 有先后顺序 事件可以出现多次 注册转化漏斗 启动APP gt APP注册页面 gt 注册结果 gt 提交订单 gt 支付成功 搜购转化漏斗 搜索商品 gt 点击商品 gt 加入购物车 gt 提交
  • 什么是UTXO

    比特币UTXO是比特币网络中的一个重要概念 它是比特币交易的基础 也是比特币的账户系统 本文将从UTXO的定义 使用方式 优点和缺点等多个方面详细介绍比特币UTXO 一 UTXO的定义 UTXO Unspent Transaction Ou
  • 超详细用profile工具分析sql语句执行及status说明

    超详细用profile工具分析sql语句执行及status说明 介绍 sql执行慢的原因有可能很多种 怎么定位呢 可以用Query Profile人工具 通过该工具可以获取一条Query 在整个执行过程中多种资源的消耗情况 如 CPU IO
  • 如何防止服务器数据轻易泄露

    如今 对于中小企业和个人用户来说 在考虑到服务器的性能与安全成本的基础上 应该如何保护自己的服务器数据呢 1 提高服务器的容错能力 容错能力指的是 当服务器出现磁盘阵列错误 发现其中一组数据出错 服务器可以自动通过其他磁盘来纠正错误 恢复到
  • deep learning编程作业总结3---一步步搭建多层神经网络及应用

    本周的主要学习了如何搭建一个多层神经网络 涉及较多的理论知识 因此本编博客将对自己所学的有关神经的知识做一个总结 图1展示的是具有4个隐藏层的神经网络结构 它的输入由x1 x2 x3构成 表示样本X具有三个特征 随后进入第一个隐藏层 该层分
  • python财务报表预测股票价格_建模股票价格数据并进行预测(统计信号模型):随机信号AR模型+Yule-Walker方程_Python...

    1 背景 针对股票市场中AR 模型的识别 建立和估计问题 利用AR 模型算法对股票价格进行预测 2 模型选取 股票的价格可视为随机信号 将此随机信号建模为 一个白噪声通过LTI系统的输出 通过原始数据求解 所建模型参数 得到模型 即可预测近
  • 华为od业务主管面试问题-我的回答

    目录 1 怎么处理项目上的需求 2 业余会不会学什么东西 3 你对加班的看法 4 你对OD的看法 5 哪里人 6 后续的发展 7 你对华为的认识 对当前岗位的了解 1 怎么处理项目上的需求 gt 项目经理和产品经理进行需求对接 gt 项目经
  • vant-list + toast分页加载,数据加载后会滚动至顶部

    vant list toast分页加载 数据加载后会滚动至顶部 主要原因是 toast组件在全局添加了 pointer event none 解决办法 在对应的van list的属性值添加 pointer event volunteer l
  • QT控件之(TableView)的居中效果

    T将tableView中的表头以及文本内容都进行居中处理 1 需要在构造函数中增加一句 以下增加的是表头的效果 ui gt tableView gt horizontalHeader gt setSectionResizeMode QHea
  • SQL注入之布尔盲注

    布尔盲注 如果确定页面注入点存在 如果页面没有回显并且没有报错信息可以考虑使用布尔盲注 布尔盲注的判断条件是页面布尔类型状态 当传递参数 id 1 and 1 1 这里以sqlilab的闯关为例 当传递参数 id 1 and 1 2 比较两
  • MyBatis学习(三):解析MyBatis的SQL映射XML文件写法和使用原理

    上面的两篇文章 分别是MyBatis的入门小程序和MyBatis的配置XML解析 有需要的可以先去看看这两篇文章 本篇文章 会来讲解SQL映射XML文件的写法以及如何使用 MyBatis真正的力量在于其映射语句 这里应该是奇迹发生的地方 S
  • Vue传参出现 Required String parameter 'username' is not present

    场景描述 在 使用axios 发送HTTP请求时 传递了后端指定的请求参数 但是后端报错 描述信息为 Required String parameter username is not present 分析问题 开始找原因 确定前端传递的参
  • jsp页面整合ECharts绘制图表(以折线图为例)

    文章目录 jsp页面整合ECharts绘制折线图 先看效果图 前端代码 后端测试代码 jsp页面整合ECharts绘制折线图 官网 https echarts apache org zh index html 官网上有demo可以直接调试样
  • 2021-06-15 好用的STF-Git项目

    好用的STF Git项目 1 基于openstf二次开发的群控管理平台 快速开始 Mac Linux centos 相关工具 测试使用版本 2 deploy stf docker 在Ubuntu上使用一键操作部署STF主服务器的脚本 1 基
  • Pyecharts——Python高级可视化

    Pyecharts是百度开源的移植到Python上的可视化工具 里面方法调用起来像是标记性语言 因此代码的可读性很强 一目了然 下面是一个绘制散点图的例子 import pyecharts options as opts from pyec
  • 出现 DeprecationWarning: BICUBIC is deprecated and will be removed in Pillow 10 的解决方法

    目录 1 问题所示 2 原理分析 3 解决方法 1 问题所示 使用plt代码模块的时候 问题如下 home kkjz anaconda3 envs py17 lib python3 7 site packages ipykernel lau
  • 强推,黑白照片一步完美上色,Picture Colorizer Pro Mac版

    今天在国外一个网站偶尔发现一个超棒的软件Picture Colorizer Pro专业版 黑白照片或老旧照片自动上色 心动不如行动 马上下载上手使用 效果超棒 它的强在在于色彩还原非常真实 有老照片的胶片感 边缘过度很精细 没有粗糙的感觉
  • 在C++中如何使用httpClient,用Newtonsoft解析JSON

    现在C 也不行了吗 网上找不到相关代码 为了搞清楚C 中如何使用httpClient和Newtonsoft 研究了一下午 我从未用C 编程 一直用C 现学现卖 https download csdn net download cnwjl 1
  • 深入浅出java并发编程(AbstractQueuedSynchronizer)(AQS)

    前言 Abstract抽象的 Ownable拥有 Synchronizer同步器 Queued队列 AbstractOwnableSynchronizer简称为AOS AbstractQueuedSynchronizer简称为AQS Abs