相关栏目
新闻资讯 >>
合作媒体 >>
展会知识 >>
当前位置:首页 >

真没想到(AQS原理解析)aqs原理,


Provides a framework for implementing blocking locks and related synchronizers (semaphores, events, etc) that rely on first-in-first-out (FIFO) wait queues. This class is designed to be a useful basis for most kinds of synchronizers that rely on a single atomic int value to represent state. Subclasses must define the protected methods that change this state, and which define what that state means in terms of this object being acquired or released. Given these, the other methods in this class carry out all queuing and blocking mechanics. Subclasses can maintain other state fields, but only the atomically updated int value manipulated using methods getState, setState and compareAndSetState is tracked with respect to synchronization.

AQS此类旨在成为大多数依赖单个原子 int 值来表示状态的同步器的有用基础。

AQS提供了一个框架来实现依赖于FIFO Thread等待队列的阻塞锁及其对应的同步器

AQS的子类必须重写AQS的protected方法(tryAcquire、tryRelease、tryAcquireShared、tryReleaseShared、isHeldExclusively),这些方法可以改变state,定义其对象被获取和释放时state的含义。其他的方法执行队列和阻塞机制,AQS子类可以维护其他状态字段,但是只有对单个原子 int 值状态更新的方法(getState, setState and compareAndSetState)会被用于同步

Subclasses should be defined as non-public internal helper classes that are used to implement the synchronization properties of their enclosing class. Class AbstractQueuedSynchronizer does not implement any synchronization interface. Instead it defines methods such as acquireInterruptibly that can be invoked as appropriate by concrete locks and related synchronizers to implement their public methods.

AQS子类应该被定义成non-public的内部帮助类来用于实现其封闭(外部)类的同步属性。

AQS不实现任何同步器接口,相反,它定义了诸如acquireInterruptively 之类的方法,这些方法可以由具体锁和相关同步器适当调用以实现它们的公共方法。下面给出AQS的字段,一个“双端队列”,一个state,再加上unsafe(提供CAS操作)

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable { /** * Head of the wait queue, lazily initialized. Except for * initialization, it is modified only via method setHead. Note: * If head exists, its waitStatus is guaranteed not to be * CANCELLED. */ private transient volatile Node head; /** * Tail of the wait queue, lazily initialized. Modified only via * method enq to add new wait node. */ private transient volatile Node tail; /** * The synchronization state. */ private volatile int state; /** * Setup to support compareAndSet. We need to natively implement * this here: For the sake of permitting future enhancements, we * cannot explicitly subclass AtomicInteger, which would be * efficient and useful otherwise. So, as the lesser of evils, we * natively implement using hotspot intrinsics API. And while we * are at it, we do the same for other CASable fields (which could * otherwise be done with atomic field updaters). */ private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long stateOffset; private static final long headOffset; private static final long tailOffset; private static final long waitStatusOffset; private static final long nextOffset; }

AQS继承了抽象类AbstractOwnableSynchronizer,这个类非常简单,只有一个变量,那就是owner线程。这个类可能涉及到ownership概念的同步器的基础

A synchronizer that may be exclusively owned by a thread. This class provides a basis for creating locks and related synchronizers that may entail a notion of ownership. The AbstractOwnableSynchronizer class itself does not manage or use this information. However, subclasses and tools may use appropriately maintained values to help control and monitor access and provide diagnostics.

public abstract class AbstractOwnableSynchronizer implements java.io.Serializable { /** * The current owner of exclusive mode synchronization. */ private transient Thread exclusiveOwnerThread; }

继续说AQS

This class supports either or both a default exclusive mode and a shared mode. When acquired in exclusive mode, attempted acquires by other threads cannot succeed. Shared mode acquires by multiple threads may (but need not) succeed. This class does not "understand" these differences except in the mechanical sense that when a shared mode acquire succeeds, the next waiting thread (if one exists) must also determine whether it can acquire as well. Threads waiting in the different modes share the same FIFO queue. Usually, implementation subclasses support only one of these modes, but both can come into play for example in a ReadWriteLock. Subclasses that support only exclusive or only shared modes need not define the methods supporting the unused mode.

AQS支持默认独占模式和共享模式中的一种或两种。 当以独占模式获取时,其他线程尝试获取不会成功。 共享模式下多个线程获取可能(但不一定)成功。 AQS不“理解”这些差异,除了机械意义上的区别,当共享模式获取成功时,下一个等待线程(如果存在)也必须确定它是否也可以获取。 在不同模式下等待的线程共享同一个 FIFO 队列。 通常,实现子类只支持这些模式中的一种,但两种模式都可以发挥作用,例如在 ReadWriteLock 中。 仅支持独占或仅共享模式的子类不需要定义支持未使用模式的方法。

This class defines a nested AbstractQueuedSynchronizer.ConditionObject class that can be used as a Condition implementation by subclasses supporting exclusive mode for which method isHeldExclusively reports whether synchronization is exclusively held with respect to the current thread, method release invoked with the current getState value fully releases this object, and acquire, given this saved state value, eventually restores this object to its previous acquired state. No AbstractQueuedSynchronizer method otherwise creates such a condition, so if this constraint cannot be met, do not use it. The behavior of AbstractQueuedSynchronizer.ConditionObject depends of course on the semantics of its synchronizer implementation.

该类定义了一个嵌套的 AbstractQueuedSynchronizer.ConditionObject 类,该类可以被支持独占模式的子类用作 Condition 实现,其中方法 isHeldExclusively 报告“同步”是否被当前线程私自占有,方法release(伴随getState、setState)完全释放此对象,恢复状态值。。。

This class provides inspection, instrumentation, and monitoring methods for the internal queue, as well as similar methods for condition objects. These can be exported as desired into classes using an AbstractQueuedSynchronizer for their synchronization mechanics.Serialization of this class stores only the underlying atomic integer maintaining state, so deserialized objects have empty thread queues. Typical subclasses requiring serializability will define a readObject method that restores this to a known initial state upon deserialization.

此类为内部队列提供检查、检测和监视方法,以及为条件对象提供类似方法。 这些可以根据需要使用 AbstractQueuedSynchronizer 的同步机制导出到类中。

此类的序列化仅存储底层原子整数维护状态,因此反序列化的对象具有空线程队列。 需要可序列化的子类需要定义一个 readObject 方法,该方法在反序列化时将其恢复到已知的初始状态。

To use this class as the basis of a synchronizer, redefine the following methods, as applicable, by inspecting and/or modifying the synchronization state using getState, setState and/or compareAndSetState:

tryAcquiretryReleasetryAcquireSharedtryReleaseSharedisHeldExclusively

子类重新这些方法,这些方法内部使用getState, setState来检查同步状态,使用compareAndSetState来修改同步状态

Each of these methods by default throws UnsupportedOperationException. Implementations of these methods must be internally thread-safe, and should in general be short and not block. Defining these methods is the only supported means of using this class. All other methods are declared final because they cannot be independently varied.

You may also find the inherited methods from AbstractOwnableSynchronizer useful to keep track of the thread owning an exclusive synchronizer. You are encouraged to use them -- this enables monitoring and diagnostic tools to assist users in determining which threads hold locks.

AQS继承AbstractOwnableSynchronizer,这个类用来追踪持有独占同步器的线程

Even though this class is based on an internal FIFO queue, it does not automatically enforce FIFO acquisition policies. The core of exclusive synchronization(独占同步机制) takes the form:

Acquire: while (!tryAcquire(arg)) { enqueue thread if it is not already queued; possibly block current thread; } Release: if (tryRelease(arg)) unblock the first queued thread;

(Shared mode is similar but may involve cascading signals.)

public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; }

Because checks in acquire are invoked before enqueuing, a newly acquiring thread may barge ahead of others that are blocked and queued.(不公平,最坏的情况是饥饿) However, you can, if desired, define tryAcquire and/or tryAcquireShared to disable barging by internally invoking one or more of the inspection methods, thereby providing a fair FIFO acquisition order. In particular, most fair synchronizers can define tryAcquire to return false if hasQueuedPredecessors (a method specifically designed to be used by fair synchronizers) returns true. Other variations are possible.

方法acquire中检查在入队之前,一个新的acquiring线程可能抢占到拿下入队的阻塞的线程前面,这是不公平的。最坏情况是线程饥饿。AQS子类可以重写tryAcquire and/or tryAcquireShared去禁止抢占,通过别的监管方法,进而提供公平的FIFO队列.In particular, 如果 hasQueuedPredecessors(一种专门设计用于公平同步器使用的方法)返回 true,大多数公平同步器可以定义 tryAcquire 以返回 false。 其他变化也是可能的。

道格李给出一个锁使用AQS子类的例子,这是一个非重入的同步器

class Mutex implements Lock, java.io.Serializable { // Our internal helper class private static class Sync extends AbstractQueuedSynchronizer { // Reports whether in locked state protected boolean isHeldExclusively() { return getState() == 1; } // Acquires the lock if state is zero public boolean tryAcquire(int acquires) { assert acquires == 1; // Otherwise unused if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } // Releases the lock by setting state to zero protected boolean tryRelease(int releases) { assert releases == 1; // Otherwise unused if (getState() == 0) throw new IllegalMonitorStateException(); setExclusiveOwnerThread(null); setState(0); return true; } // Provides a Condition Condition newCondition() { return new ConditionObject(); } // Deserializes properly private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); // reset to unlocked state } } // The sync object does all the hard work. We just forward to it. private final Sync sync = new Sync(); public void lock() { sync.acquire(1); } public boolean tryLock() { return sync.tryAcquire(1); } public void unlock() { sync.release(1); } public Condition newCondition() { return sync.newCondition(); } public boolean isLocked() { return sync.isHeldExclusively(); } public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } } /**Here is a latch class that is like a CountDownLatch except that it only requires a single signal to fire. Because a latch is non-exclusive, it uses the shared acquire and release methods. */ class BooleanLatch { private static class Sync extends AbstractQueuedSynchronizer { boolean isSignalled() { return getState() != 0; } protected int tryAcquireShared(int ignore) { return isSignalled() ? 1 : -1; } protected boolean tryReleaseShared(int ignore) { setState(1); return true; } } private final Sync sync = new Sync(); public boolean isSignalled() { return sync.isSignalled(); } public void signal() { sync.releaseShared(1); } public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } }

AQS子类一般作为内部帮助类,外部类使用AQS来提供对外接口

注明:本文章来源于互联网,如侵权请联系客服删除!