java.util.concurrent.locks

接口
java.lang.Object
  继承者 java.util.concurrent.locks.AbstractOwnableSynchronizer
      继承者 java.util.concurrent.locks.AbstractQueuedSynchronizer
所有已实现的接口:
Serializable

public abstract class AbstractQueuedSynchronizer
     
extends AbstractOwnableSynchronizer
implements Serializable

为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关同步器(信号量、事件,等等)提供一个框架。此类的设计目标是成为依靠单个原子 int 值来表示状态的大多数同步器的一个有用基础。子类必须定义更改此状态的受保护方法,并定义哪种状态对于此对象意味着被获取或被释放。假定这些条件之后,此类中的其他方法就可以实现所有排队和阻塞机制。子类可以维护其他状态字段,但只是为了获得同步而只追踪使用 getState()setState(int)compareAndSetState(int, int) 方法来操作以原子方式更新的 int 值。

应该将子类定义为非公共内部帮助器类,可用它们来实现其封闭类的同步属性。类 AbstractQueuedSynchronizer 没有实现任何同步接口。而是定义了诸如 acquireInterruptibly(int) 之类的一些方法,在适当的时候可以通过具体的锁和相关同步器来调用它们,以实现其公共方法。

此类支持默认的独占 模式和共享 模式之一,或者二者都支持。处于独占模式下时,其他线程试图获取该锁将无法取得成功。在共享模式下,多个线程获取某个锁可能(但不是一定)会获得成功。此类并不“了解”这些不同,除了机械地意识到当在共享模式下成功获取某一锁时,下一个等待线程(如果存在)也必须确定自己是否可以成功获取该锁。处于不同模式下的等待线程可以共享相同的 FIFO 队列。通常,实现子类只支持其中一种模式,但两种模式都可以在(例如)ReadWriteLock 中发挥作用。只支持独占模式或者只支持共享模式的子类不必定义支持未使用模式的方法。

此类通过支持独占模式的子类定义了一个嵌套的 AbstractQueuedSynchronizer.ConditionObject 类,可以将这个类用作 Condition 实现。isHeldExclusively() 方法将报告同步对于当前线程是否是独占的;使用当前 getState() 值调用 release(int) 方法则可以完全释放此对象;如果给定保存的状态值,那么 acquire(int) 方法可以将此对象最终恢复为它以前获取的状态。没有别的 AbstractQueuedSynchronizer 方法创建这样的条件,因此,如果无法满足此约束,则不要使用它。AbstractQueuedSynchronizer.ConditionObject 的行为当然取决于其同步器实现的语义。

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

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

使用

为了将此类用作同步器的基础,需要适当地重新定义以下方法,这是通过使用 getState()setState(int) 和/或 compareAndSetState(int, int) 方法来检查和/或修改同步状态来实现的:

默认情况下,每个方法都抛出 UnsupportedOperationException。这些方法的实现在内部必须是线程安全的,通常应该很短并且不被阻塞。定义这些方法是使用此类的 唯一 受支持的方式。其他所有方法都被声明为 final,因为它们无法是各不相同的。

您也可以查找从 AbstractOwnableSynchronizer 继承的方法,用于跟踪拥有独占同步器的线程。鼓励使用这些方法,这允许监控和诊断工具来帮助用户确定哪个线程保持锁。

即使此类基于内部的某个 FIFO 队列,它也无法强行实施 FIFO 获取策略。独占同步的核心采用以下形式:

 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;
 
(共享模式与此类似,但可能涉及级联信号。)

因为要在加入队列之前检查线程的获取状况,所以新获取的线程可能闯入 其他被阻塞的和已加入队列的线程之前。不过如果需要,可以内部调用一个或多个检查方法,通过定义 tryAcquire 和/或 tryAcquireShared 来禁用闯入。特别是 getFirstQueuedThread() 没有返回当前线程的时候,严格的 FIFO 锁定可以定义 tryAcquire 立即返回 false。只有 hasQueuedThreads() 返回 true 并且 getFirstQueuedThread 不是当前线程时,更好的非严格公平的版本才可能会立即返回 false;如果 getFirstQueuedThread 不为 null 并且不是当前线程,则产生的结果相同。出现进一步的变体也是有可能的。

对于默认闯入(也称为 greedyrenouncementconvoy-avoidance)策略,吞吐量和可伸缩性通常是最高的。尽管无法保证这是公平的或是无偏向的,但允许更早加入队列的线程先于更迟加入队列的线程再次争用资源,并且相对于传入的线程,每个参与再争用的线程都有平等的成功机会。此外,尽管从一般意义上说,获取并非“自旋”,它们可以在阻塞之前对用其他计算所使用的 tryAcquire 执行多次调用。在只保持独占同步时,这为自旋提供了最大的好处,但不是这种情况时,也不会带来最大的负担。如果需要这样做,那么可以使用“快速路径”检查来先行调用 acquire 方法,以这种方式扩充这一点,如果可能不需要争用同步器,则只能通过预先检查 hasContended() 和/或 hasQueuedThreads() 来确认这一点。

通过特殊化其同步器的使用范围,此类为部分同步化提供了一个有效且可伸缩的基础,同步器可以依赖于 int 型的 state、acquire 和 release 参数,以及一个内部的 FIFO 等待队列。这些还不够的时候,可以使用 atomic 类、自己的定制 Queue 类和 LockSupport 阻塞支持,从更低级别构建同步器。

使用示例

以下是一个非再进入的互斥锁类,它使用值 0 表示未锁定状态,使用 1 表示锁定状态。当非重入锁定不严格地需要当前拥有者线程的记录时,此类使得使用监视器更加方便。它还支持一些条件并公开了一个检测方法:

 class Mutex implements Lock, java.io.Serializable {

    // Our internal helper class
    private static class Sync extends AbstractQueuedSynchronizer {
      // Report whether in locked state
      protected boolean isHeldExclusively() { 
        return getState() == 1; 
      }

      // Acquire 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;
      }

      // Release 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;
      }
       
      // Provide a Condition
      Condition newCondition() { return new ConditionObject(); }

      // Deserialize 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));
    }
 }
 

以下是一个锁存器类,它类似于 CountDownLatch,除了只需要触发单个 signal 之外。因为锁存器是非独占的,所以它使用 shared 的获取和释放方法。

 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);
    }
 }

 

从以下版本开始:
1.5
另请参见:
序列化表格

嵌套类摘要
 class AbstractQueuedSynchronizer.ConditionObject
          AbstractQueuedSynchronizer 的 Condition 实现是 Lock 实现的基础。
 
构造方法摘要
protected AbstractQueuedSynchronizer()
          创建具有初始同步状态 0 的新 AbstractQueuedSynchronizer 实例。
 
方法摘要
 void acquire(int arg)
          以独占模式获取对象,忽略中断。
 void acquireInterruptibly(int arg)
          以独占模式获取对象,如果被中断则中止。
 void acquireShared(int arg)
          以共享模式获取对象,忽略中断。
 void acquireSharedInterruptibly(int arg)
          以共享模式获取对象,如果被中断则中止。
protected  boolean compareAndSetState(int expect, int update)
          如果当前状态值等于预期值,则以原子方式将同步状态设置为给定的更新值。
 Collection<Thread> getExclusiveQueuedThreads()
          返回包含可能正以独占模式等待获取的线程 collection。
 Thread getFirstQueuedThread()
          返回队列中第一个(等待时间最长的)线程,如果目前没有将任何线程加入队列,则返回 null. 在此实现中,该操作是以固定时间返回的,但是,如果其他线程目前正在并发修改该队列,则可能出现循环争用。
 Collection<Thread> getQueuedThreads()
          返回包含可能正在等待获取的线程 collection。
 int getQueueLength()
          返回等待获取的线程数估计值。
 Collection<Thread> getSharedQueuedThreads()
          返回包含可能正以共享模式等待获取的线程 collection。
protected  int getState()
          返回同步状态的当前值。
 Collection<Thread> getWaitingThreads(AbstractQueuedSynchronizer.ConditionObject condition)
          返回一个 collection,其中包含可能正在等待与此同步器有关的给定条件的那些线程。
 int getWaitQueueLength(AbstractQueuedSynchronizer.ConditionObject condition)
          返回正在等待与此同步器有关的给定条件的线程数估计值。
 boolean hasContended()
          查询是否其他线程也曾争着获取此同步器;也就是说,是否某个 acquire 方法已经阻塞。
 boolean hasQueuedThreads()
          查询是否有正在等待获取的任何线程。
 boolean hasWaiters(AbstractQueuedSynchronizer.ConditionObject condition)
          查询是否有线程正在等待给定的、与此同步器相关的条件。
protected  boolean isHeldExclusively()
          如果对于当前(正调用的)线程,同步是以独占方式进行的,则返回 true
 boolean isQueued(Thread thread)
          如果给定线程的当前已加入队列,则返回 true。
 boolean owns(AbstractQueuedSynchronizer.ConditionObject condition)
          查询给定的 ConditionObject 是否使用了此同步器作为其锁。
 boolean release(int arg)
          以独占模式释放对象。
 boolean releaseShared(int arg)
          以共享模式释放对象。
protected  void setState(int newState)
          设置同步状态的值。
 String toString()
          返回标识此同步器及其状态的字符串。
protected  boolean tryAcquire(int arg)
          试图在独占模式下获取对象状态。
 boolean tryAcquireNanos(int arg, long nanosTimeout)
          试图以独占模式获取对象,如果被中断则中止,如果到了给定超时时间,则会失败。
protected  int tryAcquireShared(int arg)
          试图在共享模式下获取对象状态。
 boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
          试图以共享模式获取对象,如果被中断则中止,如果到了给定超时时间,则会失败。
protected  boolean tryRelease(int arg)
          试图设置状态来反映独占模式下的一个释放。
protected  boolean tryReleaseShared(int arg)
          试图设置状态来反映共享模式下的一个释放。
 
从类 java.util.concurrent.locks.AbstractOwnableSynchronizer 继承的方法
getExclusiveOwnerThread, setExclusiveOwnerThread
 
从类 java.lang.Object 继承的方法
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

构造方法详细信息

AbstractQueuedSynchronizer

protected AbstractQueuedSynchronizer()
创建具有初始同步状态 0 的新 AbstractQueuedSynchronizer 实例。

方法详细信息

getState

protected final int getState()
返回同步状态的当前值。此操作具有 volatile 读的内存语义。

返回:
当前状态值

setState

protected final void setState(int newState)
设置同步状态的值。此操作具有 volatile 写的内存语义。

参数:
newState - 新的状态值

compareAndSetState

protected final boolean compareAndSetState(int expect,
                                           int update)
如果当前状态值等于预期值,则以原子方式将同步状态设置为给定的更新值。此操作具有 volatile 读和写的内存语义。

参数:
expect - 预期值
update - 新值
返回:
如果成功,则返回 true。返回 false 指示实际值与预期值不相等。

tryAcquire

protected boolean tryAcquire(int arg)
试图在独占模式下获取对象状态。此方法应该查询是否允许它在独占模式下获取对象状态,如果允许,则获取它。

此方法总是由执行 acquire 的线程来调用。如果此方法报告失败,则 acquire 方法可以将线程加入队列(如果还没有将它加入队列),直到获得其他某个线程释放了该线程的信号。可以用此方法来实现 Lock.tryLock() 方法。

默认实现将抛出 UnsupportedOperationException

参数:
arg - acquire 参数。该值总是传递给 acquire 方法的那个值,或者是因某个条件等待而保存在条目上的值。该值是不间断的,并且可以表示任何内容。
返回:
如果成功,则返回 true。在成功的时候,此对象已经被获取。
抛出:
IllegalMonitorStateException - 如果正在进行的获取操作将在非法状态下放置此同步器。必须以一致的方式抛出此异常,以便同步正确运行。
UnsupportedOperationException - 如果不支持独占模式

tryRelease

protected boolean tryRelease(int arg)
试图设置状态来反映独占模式下的一个释放。

此方法总是由正在执行释放的线程调用。

默认实现将抛出 UnsupportedOperationException

参数:
arg - release 参数。该值总是传递给 release 方法的那个值,或者是因某个条件等待而保存在条目上的当前状态值。该值是不间断的,并且可以表示任何内容。
返回:
如果此对象现在处于完全释放状态,从而使等待的线程都可以试图获得此对象,则返回 true;否则返回 false
抛出:
IllegalMonitorStateException - 如果正在进行的释放操作将在非法状态下放置此同步器。必须以一致的方式抛出此异常,以便同步正确运行。
UnsupportedOperationException - 如果不支持独占模式

tryAcquireShared

protected int tryAcquireShared(int arg)
试图在共享模式下获取对象状态。此方法应该查询是否允许它在共享模式下获取对象状态,如果允许,则获取它。

此方法总是由执行 acquire 线程来调用。如果此方法报告失败,则 acquire 方法可以将线程加入队列(如果还没有将它加入队列),直到获得其他某个线程释放了该线程的信号。

默认实现将抛出 UnsupportedOperationException

参数:
arg - acquire 参数。该值总是传递给 acquire 方法的那个值,或者是因某个条件等待而保存在条目上的值。该值是不间断的,并且可以表示任何内容。
返回:
在失败时返回负值;如果共享模式下的获取成功但其后续共享模式下的获取不能成功,则返回 0;如果共享模式下的获取成功并且其后续共享模式下的获取可能够成功,则返回正值,在这种情况下,后续等待线程必须检查可用性。(对三种返回值的支持使得此方法可以在只是有时候以独占方式获取对象的上下文中使用。)在成功的时候,此对象已被获取。
抛出:
IllegalMonitorStateException - 如果正在进行的获取操作将在非法状态下放置此同步器。必须以一致的方式抛出此异常,以便同步正确运行。
UnsupportedOperationException - 如果不支持共享模式

tryReleaseShared

protected boolean tryReleaseShared(int arg)
试图设置状态来反映共享模式下的一个释放。

此方法总是由正在执行释放的线程调用。

默认实现将抛出 UnsupportedOperationException

参数:
arg - release 参数。该值总是传递给 release 方法的那个值,或者是因某个条件等待而保存在条目上的当前状态值。该值是不间断的,并且可以表示任何内容。
返回:
如果此对象现在处于完全释放状态,从而使正在等待的线程都可以试图获得此对象,则返回 true;否则返回 false
抛出:
IllegalMonitorStateException - 如果正在进行的释放操作将在非法状态下放置此同步器。必须以一致的方式抛出此异常,以便同步正确运行
UnsupportedOperationException - 如果不支持共享模式

isHeldExclusively

protected boolean isHeldExclusively()
如果对于当前(正调用的)线程,同步是以独占方式进行的,则返回 true。此方法是在每次调用非等待 AbstractQueuedSynchronizer.ConditionObject 方法时调用的。(等待方法则调用 release(int)。)

默认实现将抛出 UnsupportedOperationException。此方法只是 AbstractQueuedSynchronizer.ConditionObject 方法内进行内部调用,因此,如果不使用条件,则不需要定义它。

返回:
如果同步是以独占方式进行的,则返回 true;其他情况则返回 false
抛出:
UnsupportedOperationException - 如果不支持这些条件

acquire

public final void acquire(int arg)
以独占模式获取对象,忽略中断。通过至少调用一次 tryAcquire(int) 来实现此方法,并在成功时返回。否则在成功之前,一直调用 tryAcquire(int) 将线程加入队列,线程可能重复被阻塞或不被阻塞。可以使用此方法来实现 Lock.lock() 方法。

参数:
arg - acquire 参数。此值被传送给 tryAcquire(int),但它是不间断的,并且可以表示任何内容。

acquireInterruptibly

public final void acquireInterruptibly(int arg)
                                throws InterruptedException
以独占模式获取对象,如果被中断则中止。通过先检查中断状态,然后至少调用一次 tryAcquire(int) 来实现此方法,并在成功时返回。否则在成功之前,或者线程被中断之前,一直调用 tryAcquire(int) 将线程加入队列,线程可能重复被阻塞或不被阻塞。可以使用此方法来实现 Lock.lockInterruptibly() 方法。

参数:
arg - acquire 参数。此值被传送给 tryAcquire(int),但它是不间断的,并且可以表示任何内容。
抛出:
InterruptedException - 如果当前线程被中断

tryAcquireNanos

public final boolean tryAcquireNanos(int arg,
                                     long nanosTimeout)
                              throws InterruptedException
试图以独占模式获取对象,如果被中断则中止,如果到了给定超时时间,则会失败。通过先检查中断状态,然后至少调用一次 tryAcquire(int) 来实现此方法,并在成功时返回。否则,在成功之前、线程被中断之前或者到达超时时间之前,一直调用 tryAcquire(int) 将线程加入队列,线程可能重复被阻塞或不被阻塞。可以用此方法来实现 Lock.tryLock(long, TimeUnit) 方法。

参数:
arg - acquire 参数。此值被传送给 tryAcquire(int),但它是不间断的,并且可以表示任何内容。
nanosTimeout - 等待的最长时间,以毫微秒为单位
返回:
如果获取对象,则返回 true,如果超时,则返回 false
抛出:
InterruptedException - 如果当前线程被中断

release

public final boolean release(int arg)
以独占模式释放对象。如果 tryRelease(int) 返回 true,则通过消除一个或多个线程的阻塞来实现此方法。可以使用此方法来实现 Lock.unlock() 方法

参数:
arg - release 参数。此值被传送给 tryRelease(int),但它是不间断的,并且可以表示任何内容。
返回:
tryRelease(int) 返回的值

acquireShared

public final void acquireShared(int arg)
以共享模式获取对象,忽略中断。通过至少先调用一次 tryAcquireShared(int) 来实现此方法,并在成功时返回。否则在成功之前,一直调用 tryAcquireShared(int) 将线程加入队列,线程可能重复被阻塞或不被阻塞。

参数:
arg - acquire 参数。此值被传送给 tryAcquireShared(int),但它是不间断的,并且可以表示任何内容。

acquireSharedInterruptibly

public final void acquireSharedInterruptibly(int arg)
                                      throws InterruptedException
以共享模式获取对象,如果被中断则中止。通过先检查中断状态,然后至少调用一次 tryAcquireShared(int) 来实现此方法,并在成功时返回。否则在成功或线程被中断之前,一直调用 tryAcquireShared(int) 将线程加入队列,线程可能重复被阻塞或不被阻塞。

参数:
arg - acquire 参数。此值被传送给 tryAcquireShared(int),但它是不间断的,并且可以表示任何内容。
抛出:
InterruptedException - 如果当前线程被中断

tryAcquireSharedNanos

public final boolean tryAcquireSharedNanos(int arg,
                                           long nanosTimeout)
                                    throws InterruptedException
试图以共享模式获取对象,如果被中断则中止,如果到了给定超时时间,则会失败。通过先检查中断状态,然后至少调用一次 tryAcquireShared(int) 来实现此方法,并在成功时返回。否则在成功之前、线程被中断之前或者到达超时时间之前,一直调用 tryAcquireShared(int) 将线程加入队列,线程可能重复被阻塞或不被阻塞。

参数:
arg - acquire 参数。此值被传送给 tryAcquireShared(int),但它是不间断的,并且可以表示任何内容。
nanosTimeout - 等待的最长时间,以毫微秒为单位
返回:
如果获取对象,则返回 true,如果超时,则返回 false
抛出:
InterruptedException - 如果当前线程被中断

releaseShared

public final boolean releaseShared(int arg)
以共享模式释放对象。如果 tryReleaseShared(int) 返回 true,则通过消除一个或多个线程的阻塞来实现该方法。

参数:
arg - release 参数。此值被传送给 tryReleaseShared(int),但它是不间断的,并且可以表示任何内容。
返回:
tryReleaseShared(int) 中返回的值

hasQueuedThreads

public final boolean hasQueuedThreads()
查询是否有正在等待获取的任何线程。注意,随时可能因为中断和超时而导致取消操作,返回 true 并不能保证其他任何线程都将获取对象。

在此实现中,该操作是以固定时间返回的。

返回:
如果可能有其他线程正在等待获取锁,则返回 true

hasContended

public final boolean hasContended()
查询是否其他线程也曾争着获取此同步器;也就是说,是否某个 acquire 方法已经阻塞。

在此实现中,该操作是以固定时间返回的。

返回:
如果曾经出现争用,则返回 true

getFirstQueuedThread

public final Thread getFirstQueuedThread()
返回队列中第一个(等待时间最长的)线程,如果目前没有将任何线程加入队列,则返回 null.

在此实现中,该操作是以固定时间返回的,但是,如果其他线程目前正在并发修改该队列,则可能出现循环争用。

返回:
队列中第一个(等待时间最长的)线程,如果目前没有将任何线程加入队列,则返回 null

isQueued

public final boolean isQueued(Thread thread)
如果给定线程的当前已加入队列,则返回 true。

该实现将遍历队列,以确定给定线程是否存在。

参数:
thread - 线程
返回:
如果给定线程在队列中,则返回 true
抛出:
NullPointerException - 如果 thread 为 null

getQueueLength

public final int getQueueLength()
返回等待获取的线程数估计值。该值只能是一个估计值,因为在此方法遍历内部数据结构时,线程的数量可能发生大的变化。该方法是为用来监视系统状态而设计的,不是为同步控制设计的。

返回:
正等待获取的线程估计数

getQueuedThreads

public final Collection<Thread> getQueuedThreads()
返回包含可能正在等待获取的线程 collection。因为在构造该结果时,实际线程 set 可能发生大的变化,所以返回的 collection 只是尽最大努力获得的一个估计值。返回 collection 的元素并不是以特定顺序排列的。此方法是为促进子类的构造而设计的,这些子类提供了大量的监视设施。

返回:
线程的 collection

getExclusiveQueuedThreads

public final Collection<Thread> getExclusiveQueuedThreads()
返回包含可能正以独占模式等待获取的线程 collection。此方法具有与 getQueuedThreads() 相同的属性,除了它只返回那些因独占获取而等待的线程。

返回:
线程的 collection

getSharedQueuedThreads

public final Collection<