abstractqueuedsynchronizer.html

来自「j2se5-api-zh,java文档的中文版本」· HTML 代码 · 共 1,163 行 · 第 1/5 页

HTML
1,163
字号
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><!--NewPage--><HTML><HEAD><!-- Generated by javadoc (build 1.5.0_03) on Wed Nov 02 09:51:57 CST 2005 --><META http-equiv="Content-Type" content="text/html; charset=gb2312"><TITLE>AbstractQueuedSynchronizer (Java 2 Platform SE 5.0)</TITLE><META NAME="keywords" CONTENT="java.util.concurrent.locks.AbstractQueuedSynchronizer class"><LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../stylesheet.css" TITLE="Style"><SCRIPT type="text/javascript">function windowTitle(){    parent.document.title="AbstractQueuedSynchronizer (Java 2 Platform SE 5.0)";}</SCRIPT><NOSCRIPT></NOSCRIPT></HEAD><BODY BGCOLOR="white" onload="windowTitle();"><!-- ========= START OF TOP NAVBAR ======= --><A NAME="navbar_top"><!-- --></A><A HREF="#skip-navbar_top" title="跳过导航链接"></A><TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY=""><TR><TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1"><A NAME="navbar_top_firstrow"><!-- --></A><TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">  <TR ALIGN="center" VALIGN="top">  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../../overview-summary.html"><FONT CLASS="NavBarFont1"><B>概述</B></FONT></A>&nbsp;</TD>  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>软件包</B></FONT></A>&nbsp;</TD>  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>类</B></FONT>&nbsp;</TD>  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="class-use/AbstractQueuedSynchronizer.html"><FONT CLASS="NavBarFont1"><B>使用</B></FONT></A>&nbsp;</TD>  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>树</B></FONT></A>&nbsp;</TD>  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>已过时</B></FONT></A>&nbsp;</TD>  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../../index-files/index-1.html"><FONT CLASS="NavBarFont1"><B>索引</B></FONT></A>&nbsp;</TD>  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>帮助</B></FONT></A>&nbsp;</TD>  </TR></TABLE></TD><TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM><b>Java<sup><font size=-2>TM</font></sup>&nbsp;2&nbsp;Platform<br>Standard&nbsp;Ed. 5.0</b></EM></TD></TR><TR><TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">&nbsp;上一个类&nbsp;&nbsp;<A HREF="AbstractQueuedSynchronizer.ConditionObject.html" title="java.util.concurrent.locks 中的类"><B>下一个类</B></A></FONT></TD><TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">  <A HREF="../../../../index.html@java_2Futil_2Fconcurrent_2Flocks_2FAbstractQueuedSynchronizer.html" target="_top"><B>框架</B></A>  &nbsp;&nbsp;<A HREF="AbstractQueuedSynchronizer.html" target="_top"><B>无框架</B></A>  &nbsp;&nbsp;<SCRIPT type="text/javascript">  <!--  if(window==top) {    document.writeln('<A HREF="../../../../allclasses-noframe.html"><B>所有类</B></A>');  }  //--></SCRIPT><NOSCRIPT>  <A HREF="../../../../allclasses-noframe.html"><B>所有类</B></A></NOSCRIPT></FONT></TD></TR><TR><TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">  摘要:&nbsp;<A HREF="#nested_class_summary">嵌套</A>&nbsp;|&nbsp;字段&nbsp;|&nbsp;<A HREF="#constructor_summary">构造方法</A>&nbsp;|&nbsp;<A HREF="#method_summary">方法</A></FONT></TD><TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">详细信息:&nbsp;字段&nbsp;|&nbsp;<A HREF="#constructor_detail">构造方法</A>&nbsp;|&nbsp;<A HREF="#method_detail">方法</A></FONT></TD></TR></TABLE><A NAME="skip-navbar_top"></A><!-- ========= END OF TOP NAVBAR ========= --><HR><!-- ======== START OF CLASS DATA ======== --><H2><FONT SIZE="-1">java.util.concurrent.locks</FONT><BR>类 AbstractQueuedSynchronizer</H2><PRE><A HREF="../../../lang/Object.html" title="java.lang 中的类">java.lang.Object</A>  <IMG SRC="../../../../resources/inherit.gif" ALT="继承者 "><B>java.util.concurrent.locks.AbstractQueuedSynchronizer</B></PRE><DL><DT><B>所有已实现的接口:</B> <DD>java.io.Serializable</DD></DL><HR><DL><DT><PRE>public abstract class <B>AbstractQueuedSynchronizer</B><DT>extends <A HREF="../../../lang/Object.html" title="java.lang 中的类">Object</A><DT>implements java.io.Serializable</DL></PRE><P>为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁定和相关同步器(信号量、事件,等等)提供一个框架。此类的设计目标是成为依靠单个原子 <tt>int</tt> 值来表示状态的大多数同步器的一个有用基础。子类必须定义更改此状态的受保护方法,并定义哪种状态对于此对象意味着被获取或被释放。假定这些条件之后,此类中的其他方法就可以实现所有排队和阻塞机制。子类可以维护其他状态字段,但只是为了获得同步而只追踪使用 <A HREF="AbstractQueuedSynchronizer.html#getState()"><CODE>getState()</CODE></A>、<A HREF="AbstractQueuedSynchronizer.html#setState(int)"><CODE>setState(int)</CODE></A> 和 <A HREF="AbstractQueuedSynchronizer.html#compareAndSetState(int, int)"><CODE>compareAndSetState(int, int)</CODE></A> 方法来操作以原子方式更新的 <tt>int</tt> 值。<p>应该将子类定义为非公共内部帮助器类,可用它们来实现其封闭类的同步属性。类 <tt>AbstractQueuedSynchronizer</tt> 没有实现任何同步接口。而是定义了诸如 <A HREF="AbstractQueuedSynchronizer.html#acquireInterruptibly(int)"><CODE>acquireInterruptibly(int)</CODE></A> 之类的一些方法,在适当的时候可以通过具体的锁定和相关同步器来调用它们,以实现其公共方法。 <p>此类支持默认的<em>独占</em> 模式和<em>共享</em> 模式之一,或者二者都支持。处于独占模式下时,其他线程试图获取该锁定将无法取得成功。在共享模式下,多个线程获取某个锁定可能(但不是一定)会获得成功。此类并不&ldquo;了解&rdquo;这些不同,除了机械地意识到当在共享模式下成功获取某一锁定时,下一个等待线程(如果存在)也必须确定自己是否可以成功获取该锁定。处于不同模式下的等待线程可以共享相同的 FIFO 队列。通常,实现子类只支持其中一种模式,但两种模式都可以在(例如)<A HREF="ReadWriteLock.html" title="java.util.concurrent.locks 中的接口"><CODE>ReadWriteLock</CODE></A> 中发挥作用。只支持独占模式或者只支持共享模式的子类不必定义支持未使用模式的方法。<p>此类通过支持独占模式的子类定义了一个嵌套的 <A HREF="AbstractQueuedSynchronizer.ConditionObject.html" title="java.util.concurrent.locks 中的类"><CODE>AbstractQueuedSynchronizer.ConditionObject</CODE></A> 类,可以将这个类用作 <A HREF="Condition.html" title="java.util.concurrent.locks 中的接口"><CODE>Condition</CODE></A> 实现。<A HREF="AbstractQueuedSynchronizer.html#isHeldExclusively()"><CODE>isHeldExclusively()</CODE></A> 方法将报告同步对于当前线程是否是独占的;使用当前 <A HREF="AbstractQueuedSynchronizer.html#getState()"><CODE>getState()</CODE></A> 值调用 <A HREF="AbstractQueuedSynchronizer.html#release(int)"><CODE>release(int)</CODE></A> 方法则可以完全释放此对象;如果给定保存的状态值,那么 <A HREF="AbstractQueuedSynchronizer.html#acquire(int)"><CODE>acquire(int)</CODE></A> 方法可以将此对象最终恢复为它以前获取的状态。没有别的 <tt>AbstractQueuedSynchronizer</tt> 方法创建这样的条件,因此,如果无法满足此约束,则不要使用它。<A HREF="AbstractQueuedSynchronizer.ConditionObject.html" title="java.util.concurrent.locks 中的类"><CODE>AbstractQueuedSynchronizer.ConditionObject</CODE></A> 的行为当然取决于其同步器实现的语义。 <p> 此类为内部队列提供了检查、检测和监视方法,还为 condition 对象提供了类似方法。可以根据需要使用用于其同步机制的 <tt>AbstractQueuedSynchronizer</tt> 将这些方法导出到类中。<p> 此类的序列化只存储维护状态的基础原子整数,因此已序列化的对象拥有空的线程队列。需要可序列化的典型子类将定义一个 <tt>readObject</tt> 方法,该方法在反序列化时将此对象恢复到某个已知初始状态。<h3>使用</h3><p> 为了将此类用作同步器的基础,需要适当地重新定义以下方法,这是通过使用 <A HREF="AbstractQueuedSynchronizer.html#getState()"><CODE>getState()</CODE></A>、<A HREF="AbstractQueuedSynchronizer.html#setState(int)"><CODE>setState(int)</CODE></A> 和/或 <A HREF="AbstractQueuedSynchronizer.html#compareAndSetState(int, int)"><CODE>compareAndSetState(int, int)</CODE></A> 方法来检查和/或修改同步状态来实现的: <ul> <li> <A HREF="AbstractQueuedSynchronizer.html#tryAcquire(int)"><CODE>tryAcquire(int)</CODE></A> <li> <A HREF="AbstractQueuedSynchronizer.html#tryRelease(int)"><CODE>tryRelease(int)</CODE></A> <li> <A HREF="AbstractQueuedSynchronizer.html#tryAcquireShared(int)"><CODE>tryAcquireShared(int)</CODE></A> <li> <A HREF="AbstractQueuedSynchronizer.html#tryReleaseShared(int)"><CODE>tryReleaseShared(int)</CODE></A> <li> <A HREF="AbstractQueuedSynchronizer.html#isHeldExclusively()"><CODE>isHeldExclusively()</CODE></A></ul>默认情况下,每个方法都抛出 <A HREF="../../../lang/UnsupportedOperationException.html" title="java.lang 中的类"><CODE>UnsupportedOperationException</CODE></A>。这些方法的实现在内部必须是线程安全的,通常应该很短并且不被阻塞。定义这些方法是使用此类的<em>惟一</em> 受支持的方式。其他所有方法都被声明为 <tt>final</tt>,因为它们无法是各不相同的。<p> 即使此类基于内部的某个 FIFO 队列,它也无法强行实施 FIFO 获取策略。独占同步的核心采用以下形式: <pre> Acquire:     while (!tryAcquire(arg)) {        <em>enqueue thread if it is not already queued</em>;        <em>possibly block current thread</em>;     } Release:     if (tryRelease(arg))        <em>unblock the first queued thread</em>; </pre>(共享模式与此类似,但可能涉及级联信号。)<p> 因为要在加入队列之前检查线程的获取状况,所以新获取的线程可能<em>闯入</em> 其他被阻塞的和已加入队列的线程之前。不过如果需要,可以内部调用一个或多个检查方法,通过定义 <tt>tryAcquire</tt> 和/或 <tt>tryAcquireShared</tt> 来禁用闯入。特别是 <A HREF="AbstractQueuedSynchronizer.html#getFirstQueuedThread()"><CODE>getFirstQueuedThread()</CODE></A> 没有返回当前线程的时候,严格的 FIFO 锁定可以定义 <tt>tryAcquire</tt> 立即返回 <tt>false</tt>。只有 <A HREF="AbstractQueuedSynchronizer.html#hasQueuedThreads()"><CODE>hasQueuedThreads()</CODE></A> 返回 <tt>true</tt> 并且 <tt>getFirstQueuedThread</tt> 不是当前线程时,更好的非严格公平的版本才可能会立即返回 <tt>false</tt>;或者如果 <tt>getFirstQueuedThread</tt> 不为 null 并且不是当前线程,则产生的结果相同。出现进一步的变体也是有可能的。<p> 对于默认闯入(也称为 <em>greedy</em>、<em>renouncement</em> 和 <em>convoy-avoidance</em>)策略,吞吐量和可伸缩性通常是最高的。尽管无法保证这是公平的或是无偏向的,但允许更早加入队列的线程先于更迟加入队列的线程再次争用资源,并且相对于传入的线程,每个参与再争用的线程都有平等的成功机会。此外,尽管从一般意义上说,获取并非&ldquo;自旋&rdquo;,它们可以在阻塞之前对用其他计算所使用的 <tt>tryAcquire</tt> 执行多次调用。在只保持独占同步时,这为自旋提供了最大的好处,但不是这种情况时,也不会带来最大的负担。如果需要这样做,那么可以使用&ldquo;快速路径&rdquo;检查来先行调用 acquire 方法,以这种方式扩充这一点,如果可能不需要争用同步器,则只能通过预先检查 <A HREF="AbstractQueuedSynchronizer.html#hasContended()"><CODE>hasContended()</CODE></A> 和/或 <A HREF="AbstractQueuedSynchronizer.html#hasQueuedThreads()"><CODE>hasQueuedThreads()</CODE></A> 来确认这一点。<p> 通过特殊化其同步器的使用范围,此类为部分同步化提供了一个有效且可伸缩的基础,同步器可以依赖于 <tt>int</tt> 型的 state、acquire 和 release 参数,以及一个内部的 FIFO 等待队列。这些还不够的时候,可以使用 <A HREF="../atomic/package-summary.html"><CODE>atomic</CODE></A> 类、自己的定制 <A HREF="../../Queue.html" title="java.util 中的接口"><CODE>Queue</CODE></A> 类和 <A HREF="LockSupport.html" title="java.util.concurrent.locks 中的类"><CODE>LockSupport</CODE></A> 阻塞支持,从更低级别构建同步器。 <h3>用例</h3><p>以下是一个非再进入的互斥锁定类,它使用值 0 表示未锁定状态,使用 1 表示锁定状态。它还支持一些条件并公开了一个检测方法: <pre> 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        return compareAndSetState(0, 1);      }      // Release the lock by setting state to zero      protected boolean tryRelease(int releases) {        assert releases == 1; // Otherwise unused        if (getState() == 0) throw new IllegalMonitorStateException();        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));    } } </pre><p> 以下是一个锁存器类,它类似于 <A HREF="../CountDownLatch.html" title="java.util.concurrent 中的类"><CODE>CountDownLatch</CODE></A>,除了只需要触发单个 <tt>signal</tt> 之外。因为锁存器是非独占的,所以它使用 <tt>shared</tt> 的获取和释放方法。 <pre> 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);    } }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?