1.整体介绍
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(int) and compareAndSetState(int, int)
is tracked with respect to synchronization.
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(int) that can be invoked as
appropriate by concrete locks and related synchronizers to
implement their public methods.
提供了一个框架,用于实现基于FIFO等待队列的阻塞锁和相关同步器(semaphores, events等等)。该类设计作为使用单个原子整型值表示状态的大多数同步器的基类。子类必须重写改变该状态的保护方法,并指示当锁对象被获取和释放的时候该状态是什么含义。给定这些以后,该类的其他方法实现了所有排队和阻塞机制。子类仅可以通过getState() setState compareAndSetState方法原子更新状态值。
子类应该定义成外部类的非公共的内部助手类。 AbstractQueuedSynchronizer不实现任何同步接口。相反,它定义了诸如acquireInterruptibly(int)之类的方法,实际的类和相关的同步器可以调用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.
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(int) invoked with the current
getState() value fully releases this object, and acquire(int), 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.
该类支持独占、共享模式其中一个或者同时支持。仅支持独占模式或仅支持共享模式的子类无需定义支持未使用模式的方法。
在不同模式下等待的线程共享同一个FIFO队列。
此类定义了嵌套类AbstractQueuedSynchronizer.ConditionObject, 用于支持独占模式子类实现Condition。isHeldExclusively()报告当前线程是否是独占模式,release(int)方法使用当前getState()值进行调用并完全释放该对象,acquire(int)最终会还原成之前获取的状态的。没有其他的AQS方法会创建一个条件,如果无法满足约束条件,就不要使用它。
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.
此类提供内部队列的检查、检测和监视的方法,条件对象也有类似的方法。这些可以在使用AQS作为同步机制的类中运用。
该类的序列化只存储状态值,因此反序列化的对象线程队列为空。子类需要定义readObject()。
2.用法介绍
Usage
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(int) and/or
compareAndSetState(int, int):
tryAcquire(int)
tryRelease(int)
tryAcquireShared(int)
tryReleaseShared(int)
isHeldExclusively()
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.
要使用该类作为同步器的基类,需要使用getState setState cas等方法检查或修改同步状态来重定义如下方法:
- tryAcquire(int)
tryRelease(int)
tryAcquireShared(int)
tryReleaseShared(int)
isHeldExclusively()
默认情况下,这些方法都会抛出UnsupportedOperationException。这些方法的实现必须是内部线程安全的,并且应该是简短和非阻塞的。定义这些方法是使用此类唯一的方法。所有其他的方法都被声明为final。
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.
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.)
你可能会发现从AQS继承下来的方法对于追踪持有独占同步器的线程很有用。建议使用它们——这些监视和诊断工具能够帮助用户确定哪些线程持有锁。
即使该类是基于内部FIFO队列,也不会自动执行FIFO获取策略,独占同步形式如代码所示。
共享模式类似,但是可能会涉及到级联signals。
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.
因为获取锁时,在入队前先进行了检查,因此该新线程可能会先于其他阻塞和排队的线程获得锁。但是,可以通过定义tryAcquire或tryAcquireShared内部调用一个或多个检查方法来禁止插队,以获得一个公平的FIFO获取锁的顺序。特别地,大多数公平同步器定义的tryAcquire方法在hasQueuedPredecessors()返回true情况下返回false。
Throughput and scalability are generally highest for the default
barging (also known as greedy, renouncement, and convoy-
avoidance) strategy. While this is not guaranteed to be fair or
starvation-free, earlier queued threads are allowed to recontend
before later queued threads, and each recontention has an
unbiased chance to succeed against incoming threads. Also, while
acquires do not "spin" in the usual sense, they may perform
multiple invocations of tryAcquire interspersed with other
computations before blocking. This gives most of the benefits of
spins when exclusive synchronization is only briefly held, without
most of the liabilities when it isn't. If so desired, you can augment
this by preceding calls to acquire methods with "fast-path" checks,
possibly prechecking hasContended() and/or
hasQueuedThreads() to only do so if the synchronizer is likely not
to be contended.
This class provides an efficient and scalable basis for
synchronization in part by specializing its range of use to
synchronizers that can rely on int state, acquire, and release
parameters, and an internal FIFO wait queue. When this does not
suffice, you can build synchronizers from a lower level using
atomic classes, your own custom Queue classes, and
LockSupport blocking support.
默认的插队策略能够提供最高的吞吐量和可伸缩性。获取锁不是通常意义上的自旋,但它们会在阻塞之前多次调用tryAcquire以及其他计算。这在独占同步很简短的情况下提供了自旋的大部分好处,而不用付出太多代价。如果需要,可以进行预先检查 hasContended() 或hasQueuedThreads() 来增强此功能。
如果此类还不够用,可以使用原子类、自己定义的Queue类和LockSupport阻塞工具来构建自己的同步器。
3.使用示例
Usage Examples
Here is a non-reentrant mutual exclusion lock class that uses the
value zero to represent the unlocked state, and one to represent
the locked state. While a non-reentrant lock does not strictly
require recording of the current owner thread, this class does so
anyway to make usage easier to monitor. It also supports
conditions and exposes one of the instrumentation methods:
如下实现的是一个非重入的互斥锁,0表示解锁状态,1表示锁定状态。非重入锁无需记录当前获取锁的线程,但是这里仍然记录了,以便更容易监视使用情况。并支持条件。
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.
如下是一个类似于CountDownLatch的latch类,但是支持一个信号。因为latch是非独占的,其使用共享的模式。
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);
}
}
网友评论