﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-yuyee-随笔分类-concurrent</title><link>http://www.blogjava.net/yuyee/category/46790.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 09 Nov 2010 21:33:46 GMT</lastBuildDate><pubDate>Tue, 09 Nov 2010 21:33:46 GMT</pubDate><ttl>60</ttl><item><title>AbstractQueuedSynchronizer看看</title><link>http://www.blogjava.net/yuyee/archive/2010/11/09/337625.html</link><dc:creator>羔羊</dc:creator><author>羔羊</author><pubDate>Tue, 09 Nov 2010 07:30:00 GMT</pubDate><guid>http://www.blogjava.net/yuyee/archive/2010/11/09/337625.html</guid><description><![CDATA[<div><img src="http://www.blogjava.net/images/blogjava_net/yuyee/sync.jpg" width="621" height="310" alt="" /><br />
</div>
<div>API中的解释：为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁定和相关同步器（信号量、事件，等等）提供一个框架。此类的设计目标是成为依靠单个原子 <tt>int</tt>
值来表示状态的大多数同步器的一个有用基础。子类必须定义更改此状态的受保护方法，并定义哪种状态对于此对象意味着被获取或被释放。假定这些条件之后，此类中的其他方法就可以实现所有排队和阻塞机制。子类可以维护其他状态字段，但只是为了获得同步而只追踪使用
<a href=""><code>getState()</code></a>、<a href="=""><code>getState()</code></a>、<a href="="  "=""><code>getState()</code></a>、<a href=""><code>setState(int)</code></a>
和 <a href=""><code>compareAndSetState(int,
int)</code></a> 方法来操作以原子方式更新的 <tt>int</tt> 值。</div>
<div>此类采用模板模式设计，此类为一个抽象类，但是没抽象方法，每个sync子类需要实现5个受保护的方法</div>
<div><img src="http://www.blogjava.net/images/blogjava_net/yuyee/shou.jpg" width="362" height="97" alt="" /><br />
</div>
<div>这个5个方法在AbstractQueuedSynchronizer 都抛出throw new UnsupportedOperationException();</div>
<div>AbstractQueuedSynchronizer&nbsp;中有3个属性：主要声明一个状态和一个wait queue,通过</div>
<div><br />
</div>
<div><img src="http://www.blogjava.net/images/blogjava_net/yuyee/state.jpg" width="611" height="338" alt="" /></div>
<div>wait queue中Node 为一个双向链表，需要去理解Node中几个静态字段值的意义，下面为他的源码：</div>
<div>
<div>static final class Node {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/** waitStatus value to indicate thread has cancelled */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;static final int CANCELLED = &nbsp;1;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/** waitStatus value to indicate successor's thread needs unparking */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;static final int SIGNAL &nbsp; &nbsp;= -1;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/** waitStatus value to indicate thread is waiting on condition */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;static final int CONDITION = -2;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/** Marker to indicate a node is waiting in shared mode */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;static final Node SHARED = new Node();</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/** Marker to indicate a node is waiting in exclusive mode */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;static final Node EXCLUSIVE = null;</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/**</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * Status field, taking on only the values:</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; SIGNAL: &nbsp; &nbsp; The successor of this node is (or will soon be)</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; blocked (via park), so the current node must</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; unpark its successor when it releases or</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cancels. To avoid races, acquire methods must</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; first indicate they need a signal,</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; then retry the atomic acquire, and then,</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; on failure, block.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; CANCELLED: &nbsp;This node is cancelled due to timeout or interrupt.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Nodes never leave this state. In particular,</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a thread with cancelled node never again blocks.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; CONDITION: &nbsp;This node is currently on a condition queue.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; It will not be used as a sync queue node until</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; transferred. (Use of this value here</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; has nothing to do with the other uses</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; of the field, but simplifies mechanics.)</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * &nbsp; 0: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;None of the above</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; *</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * The values are arranged numerically to simplify use.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * Non-negative values mean that a node doesn't need to</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * signal. So, most code doesn't need to check for particular</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * values, just for sign.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; *</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * The field is initialized to 0 for normal sync nodes, and</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * CONDITION for condition nodes. &nbsp;It is modified only using</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * CAS.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;volatile int waitStatus;</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/**</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * Link to predecessor node that current node/thread relies on</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * for checking waitStatus. Assigned during enqueing, and nulled</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * out (for sake of GC) only upon dequeuing. &nbsp;Also, upon</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * cancellation of a predecessor, we short-circuit while</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * finding a non-cancelled one, which will always exist</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * because the head node is never cancelled: A node becomes</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * head only as a result of successful acquire. A</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * cancelled thread never succeeds in acquiring, and a thread only</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * cancels itself, not any other node.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;volatile Node prev;</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/**</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * Link to the successor node that the current node/thread</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * unparks upon release. Assigned once during enqueuing, and</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * nulled out (for sake of GC) when no longer needed. &nbsp;Upon</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * cancellation, we cannot adjust this field, but can notice</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * status and bypass the node if cancelled. &nbsp;The enq operation</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * does not assign next field of a predecessor until after</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * attachment, so seeing a null next field does not</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * necessarily mean that node is at end of queue. However, if</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * a next field appears to be null, we can scan prev's from</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * the tail to double-check.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;volatile Node next;</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/**</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * The thread that enqueued this node. &nbsp;Initialized on</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * construction and nulled out after use.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;volatile Thread thread;</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/**</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * Link to next node waiting on condition, or the special</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * value SHARED. &nbsp;Because condition queues are accessed only</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * when holding in exclusive mode, we just need a simple</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * linked queue to hold nodes while they are waiting on</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * conditions. They are then transferred to the queue to</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * re-acquire. And because conditions can only be exclusive,</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * we save a field by using special value to indicate shared</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * mode.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Node nextWaiter;</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/**</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * Returns true if node is waiting in shared mode</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;final boolean isShared() {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return nextWaiter == SHARED;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/**</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * Returns previous node, or throws NullPointerException if</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * null. &nbsp;Use when predecessor cannot be null.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * @return the predecessor of this node</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;final Node predecessor() throws NullPointerException {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Node p = prev;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (p == null)</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throw new NullPointerException();</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;else</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return p;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Node() { &nbsp; &nbsp;// Used to establish initial head or SHARED marker</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Node(Thread thread, Node mode) { &nbsp; &nbsp; // Used by addWaiter</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this.nextWaiter = mode;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this.thread = thread;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Node(Thread thread, int waitStatus) { // Used by Condition</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this.waitStatus = waitStatus;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this.thread = thread;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div><br />
</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp;}</div>
</div>
<div>获取锁定调用的方法，其实这个方法是阻塞的：</div>
<div>
<div>&nbsp;&nbsp;public final void acquire(int arg) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (!tryAcquire(arg) &amp;&amp;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;acquireQueued(addWaiter(Node.EXCLUSIVE), arg))</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;selfInterrupt();</div>
<div>&nbsp;&nbsp; &nbsp;}</div>
</div>
<div>如果获取不成功则调用如下方法：
</div>
<div>
<div>&nbsp;&nbsp; final boolean acquireQueued(final Node node, int arg) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;try {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;boolean interrupted = false;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for (;;) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;final Node p = node.predecessor();</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (p == head &amp;&amp; tryAcquire(arg)) {//当节点是头节点且独占时才返回</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;setHead(node);</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p.next = null; // help GC</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return interrupted;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (shouldParkAfterFailedAcquire(p, node) &amp;&amp;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;parkAndCheckInterrupt())//阻塞并判断是否打断，其实这个判断才是自旋锁真正的猥琐点，</div>
<div>意思是如果你的前继节点不是head,而且当你的前继节点状态是Node.SIGNAL时，你这个线程将被park()，直到另外的线程release时,发现head.next是你这个node时，才unpark，你才能继续循环并获取锁</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;interrupted = true;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div>shouldParkAfterFailedAcquire这个方法删除所有waitStatus&gt;0也就是CANCELLED状态的Node,并设置前继节点为signal</div>
<div>
<div>&nbsp;private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;int s = pred.waitStatus;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (s &lt; 0)</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/*</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; * This node has already set status asking a release</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; * to signal it, so it can safely park</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return true;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (s &gt; 0) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/*</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; * Predecessor was cancelled. Skip over predecessors and</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; * indicate retry.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span> &nbsp; &nbsp;do {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>node.prev = pred = pred.prev;</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span> &nbsp; &nbsp;} while (pred.waitStatus &gt; 0);</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span> &nbsp; &nbsp;pred.next = node;</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;else</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/*</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; * Indicate that we need a signal, but don't park yet. Caller</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; * will need to retry to make sure it cannot acquire before</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; * parking.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;compareAndSetWaitStatus(pred, 0, Node.SIGNAL);</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;return false;</div>
<div>&nbsp;&nbsp; &nbsp;}</div>
</div>
<div><br />
</div>
<div><br />
</div>
<div>使用LockSupport.park(this)，禁用当前线程</div>
<div>
<div style="padding-right: 32px; padding-left: 32px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; padding-bottom: 32px; border-left-color: #bbbbbb; padding-top: 32px; ">private final boolean parkAndCheckInterrupt() {</div>
<div style="padding-right: 32px; padding-left: 32px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; padding-bottom: 32px; border-left-color: #bbbbbb; padding-top: 32px; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;LockSupport.park(this);//block</div>
<div style="padding-right: 32px; padding-left: 32px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; padding-bottom: 32px; border-left-color: #bbbbbb; padding-top: 32px; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;return Thread.interrupted();</div>
<div style="padding-right: 32px; padding-left: 32px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; padding-bottom: 32px; border-left-color: #bbbbbb; padding-top: 32px; ">&nbsp;&nbsp; &nbsp;}</div>
</div>
<div>释放锁：</div>
<div>
<div>&nbsp;&nbsp; &nbsp;public final boolean release(int arg) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (tryRelease(arg)) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Node h = head;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (h != null &amp;&amp; h.waitStatus != 0)</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;unparkSuccessor(h);//unblock</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return true;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;return false;</div>
<div>&nbsp;&nbsp; &nbsp;}</div>
</div>
<div>
<div>private void unparkSuccessor(Node node) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/*</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * Try to clear status in anticipation of signalling. &nbsp;It is</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * OK if this fails or if status is changed by waiting thread.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;compareAndSetWaitStatus(node, Node.SIGNAL, 0);</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/*</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * Thread to unpark is held in successor, which is normally</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * just the next node. &nbsp;But if cancelled or apparently null,</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * traverse backwards from tail to find the actual</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * non-cancelled successor.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Node s = node.next;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (s == null || s.waitStatus &gt; 0) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;s = null;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for (Node t = tail; t != null &amp;&amp; t != node; t = t.prev)</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (t.waitStatus &lt;= 0)</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;s = t;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (s != null)</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;LockSupport.unpark(s.thread);</div>
<div>&nbsp;&nbsp; &nbsp;}</div>
</div>
<div><br />
</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;} catch (RuntimeException ex) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cancelAcquire(node);</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throw ex;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div>&nbsp;&nbsp; &nbsp;}</div>
</div>
<div>
<div>&nbsp;&nbsp;</div>
</div>
<div><br />
</div>
<div>看下ReentrantLock锁中sync的实现：</div>
<div>
<div>&nbsp;static abstract class Sync extends AbstractQueuedSynchronizer {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;private static final long serialVersionUID = -5179523762034025860L;</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/**</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * Performs {@link Lock#lock}. The main reason for subclassing</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * is to allow fast path for nonfair version.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;abstract void lock();</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/**</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * Performs non-fair tryLock. &nbsp;tryAcquire is</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * implemented in subclasses, but both need nonfair</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * try for trylock method.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;final boolean nonfairTryAcquire(int acquires) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;final Thread current = Thread.currentThread();</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int c = getState();</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (c == 0) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (compareAndSetState(0, acquires)) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;setExclusiveOwnerThread(current);</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return true;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;else if (current == getExclusiveOwnerThread()) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int nextc = c + acquires;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (nextc &lt; 0) // overflow</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throw new Error("Maximum lock count exceeded");</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;setState(nextc);</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return true;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return false;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;protected final boolean tryRelease(int releases) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int c = getState() - releases;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (Thread.currentThread() != getExclusiveOwnerThread())</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throw new IllegalMonitorStateException();</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;boolean free = false;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (c == 0) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;free = true;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;setExclusiveOwnerThread(null);</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;setState(c);</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return free;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;protected final boolean isHeldExclusively() {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// While we must in general read state before owner,</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// we don't need to do so to check if current thread is owner</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return getExclusiveOwnerThread() == Thread.currentThread();</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;final ConditionObject newCondition() {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return new ConditionObject();</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// Methods relayed from outer class</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;final Thread getOwner() {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return getState() == 0 ? null : getExclusiveOwnerThread();</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;final int getHoldCount() {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return isHeldExclusively() ? getState() : 0;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;final boolean isLocked() {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return getState() != 0;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div><br />
</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/**</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * Reconstitutes this lock instance from a stream.</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; * @param s the stream</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; */</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;private void readObject(java.io.ObjectInputStream s)</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throws java.io.IOException, ClassNotFoundException {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;s.defaultReadObject();</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;setState(0); // reset to unlocked state</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div>&nbsp;&nbsp; &nbsp;}</div>
</div>
<div>非公平规则下nonfairTryAcquire，获取当前锁的state,通过CAS原子操作设置为1，并将当前线程设置为独占线程，如果当前线程已经拿了锁，则state增加1</div>
<div>公平锁中&nbsp;有如下判断：</div>
<div>if (isFirst(current) &amp;&amp;//判断头元素</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;compareAndSetState(0, acquires)) {</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;setExclusiveOwnerThread(current);</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return true;</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div>
<div>在获取锁步骤：</div>
<div>1.调用tryAcquire来获取，如果失败，则进入2</div>
<div>2.调用addWaiter，以独占模式将node放到tail位置</div>
<div>3.调用acquireQueued方法，此方法阻塞，直到node的pre为head,并成功获取锁定，也可能存在阻塞并打断情况</div>
<div>释放锁的步骤：</div>
<div>1.放弃排他锁持有权</div>
<div>2.unpark 节点的下一个blocked节点</div>
<div><br />
</div>
<div>公平锁与非公平锁：从代码上看，非公平锁是让当前线程优先独占，而公平锁则是让等待时间最长的线程优先，非公平的可能让其他线程没机会执行，而公平的则可以让等待时间最长的先执行，但是性能上会差点</div>
<img src ="http://www.blogjava.net/yuyee/aggbug/337625.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yuyee/" target="_blank">羔羊</a> 2010-11-09 15:30 <a href="http://www.blogjava.net/yuyee/archive/2010/11/09/337625.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>同步包中的定时器</title><link>http://www.blogjava.net/yuyee/archive/2010/11/01/336694.html</link><dc:creator>羔羊</dc:creator><author>羔羊</author><pubDate>Mon, 01 Nov 2010 07:48:00 GMT</pubDate><guid>http://www.blogjava.net/yuyee/archive/2010/11/01/336694.html</guid><description><![CDATA[<div>
<div><span style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">ScheduledExecutorService</span><span style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;利用线程池进行调度任务，内部使用一个DelayedWorkQueue实现，返回ScheduledFuture，而DelayQueue是用优先级队列PriorityQueue实现的一个阻塞队列，</span><span style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">优先队列的比较基准值是时间</span></div>
<div>
<div style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;&nbsp;private static class DelayedWorkQueue&nbsp;</div>
<div style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;extends AbstractCollection&lt;Runnable&gt;&nbsp;</div>
<div style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;implements BlockingQueue&lt;Runnable&gt; {</div>
<div style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</div>
<div style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;private final DelayQueue&lt;ScheduledFutureTask&gt; dq = new DelayQueue&lt;ScheduledFutureTask&gt;();</div>
<div style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">}</div>
<div style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</div>
<div>
<div><font  face="Arial, sans-serif, Helvetica, Tahoma" size="3"><span  style="font-size: 12px; line-height: 18px;">public class DelayQueue&lt;E extends Delayed&gt; extends AbstractQueue&lt;E&gt;</span></font></div>
<div><font  face="Arial, sans-serif, Helvetica, Tahoma" size="3"><span  style="font-size: 12px; line-height: 18px;">&nbsp;&nbsp; &nbsp;implements BlockingQueue&lt;E&gt; {</span></font></div>
<div><font  face="Arial, sans-serif, Helvetica, Tahoma" size="3"><span  style="font-size: 12px; line-height: 18px;"><br />
</span></font></div>
<div><font  face="Arial, sans-serif, Helvetica, Tahoma" size="3"><span  style="font-size: 12px; line-height: 18px;">&nbsp;&nbsp; &nbsp;private transient final ReentrantLock lock = new ReentrantLock();</span></font></div>
<div><font  face="Arial, sans-serif, Helvetica, Tahoma" size="3"><span  style="font-size: 12px; line-height: 18px;">&nbsp;&nbsp; &nbsp;private transient final Condition available = lock.newCondition();</span></font></div>
<div><font  face="Arial, sans-serif, Helvetica, Tahoma" size="3"><span  style="font-size: 12px; line-height: 18px;">&nbsp;&nbsp; &nbsp;private final PriorityQueue&lt;E&gt; q = new PriorityQueue&lt;E&gt;();</span></font></div>
</div>
<div style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</div>
<div style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">下面为一个小例:</div>
</div>
</div>
<div>public class ConcurrentTimer {</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public static void main(String[] args) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>new ConcurrentTimer().getScheduledExecutorService();</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public void getScheduledExecutorService() {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>ScheduledExecutorService service = Executors.newScheduledThreadPool(10);</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>service.scheduleAtFixedRate(new Command(), 1, 1, TimeUnit.SECONDS);</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public class Command implements Runnable {</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>public void run() {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>System.out.println("Command");</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div>}</div>
<img src ="http://www.blogjava.net/yuyee/aggbug/336694.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yuyee/" target="_blank">羔羊</a> 2010-11-01 15:48 <a href="http://www.blogjava.net/yuyee/archive/2010/11/01/336694.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>volatile</title><link>http://www.blogjava.net/yuyee/archive/2010/11/01/336669.html</link><dc:creator>羔羊</dc:creator><author>羔羊</author><pubDate>Mon, 01 Nov 2010 06:04:00 GMT</pubDate><guid>http://www.blogjava.net/yuyee/archive/2010/11/01/336669.html</guid><description><![CDATA[volatile语义：告诉处理器，不要到工作内存中找我，而是直接到主存中操作我，多线程或者多核环境下，变量共享
<div>使用volatile要注意，他只能保证可见性，但不能保证原子性；</div>
<div>如i++之类的操作，他分为read i的值，之后执行i+1</div>
<div>当出现并发情况时，1线程read i的值，而2线程修改了i的值，这个时候1线程如果再将值刷到主存的话就会造成覆盖。</div>
<div>可以通过synchronized在同步代码段，保证原子性</div>
<div>或者使用jdk1.5的原子包</div>
<div><br />
</div>
<img src ="http://www.blogjava.net/yuyee/aggbug/336669.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yuyee/" target="_blank">羔羊</a> 2010-11-01 14:04 <a href="http://www.blogjava.net/yuyee/archive/2010/11/01/336669.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>生产者消费者</title><link>http://www.blogjava.net/yuyee/archive/2010/11/01/336643.html</link><dc:creator>羔羊</dc:creator><author>羔羊</author><pubDate>Sun, 31 Oct 2010 16:47:00 GMT</pubDate><guid>http://www.blogjava.net/yuyee/archive/2010/11/01/336643.html</guid><description><![CDATA[<div>package com.google.study.MQ;</div>
<div><br />
</div>
<div>import java.util.LinkedList;</div>
<div>import java.util.List;</div>
<div>import java.util.concurrent.locks.Condition;</div>
<div>import java.util.concurrent.locks.ReentrantLock;</div>
<div><br />
</div>
<div>public class MessageQueue {</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private List&lt;Message&gt; messageList = new LinkedList&lt;Message&gt;();</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private final ReentrantLock lock = new ReentrantLock();</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private Condition notFull = lock.newCondition();</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private Condition notEmpty = lock.newCondition();</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private Integer maxNum = 5;</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private Integer minNum = 0;</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public int size() {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>return messageList.size();</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public void produce(Message e) throws InterruptedException {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>try {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>lock.lock();</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>while (messageList.size() == maxNum) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>notFull.await();</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>messageList.add(e);</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>notEmpty.signal();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>} finally {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>lock.unlock();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public void consume() {</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>try {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>lock.lock();</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>while (messageList.size() == minNum) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>notEmpty.await();</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>messageList.get(0);</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>messageList.remove(0);</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>notFull.signal();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>} catch (Exception e) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>e.printStackTrace();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>} finally {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>lock.unlock();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div>}</div>
<div>
<div>package com.google.study.MQ;</div>
<div><br />
</div>
<div>public class Consume implements Runnable {</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private MessageQueue queue;</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public Consume(MessageQueue queue) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>this.queue = queue;</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>@Override</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public void run() {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>while (true) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>queue.consume();</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>System.out.println(queue.size());</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>try {</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>Thread.sleep(50);</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>} catch (InterruptedException e) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>// TODO Auto-generated catch block</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>e.printStackTrace();</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div>}</div>
</div>
<div><br />
</div>
<div>
<div>package com.google.study.MQ;</div>
<div><br />
</div>
<div>public class Produce implements Runnable {</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private MessageQueue queue;</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public Produce(MessageQueue queue) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>this.queue = queue;</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>@Override</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public void run() {</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>while (true) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>try {</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>queue.produce(getMessage());</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>Thread.sleep(100);</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>} catch (InterruptedException e) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>// TODO Auto-generated catch block</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>e.printStackTrace();</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private Message getMessage() {</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>Message m = new Message();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>m.setName("1");</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>m.setValue(1);</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>return m;</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div>}</div>
</div>
<div>
<div>package com.google.study.MQ;</div>
<div><br />
</div>
<div>import java.io.Serializable;</div>
<div><br />
</div>
<div>public class Message implements Serializable {</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private int value;</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private String name;</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public int getValue() {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>return value;</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public void setValue(int value) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>this.value = value;</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public String getName() {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>return name;</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div>
<div>package com.google.study.MQ;</div>
<div><br />
</div>
<div>public class Test {</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public static void main(String[] args) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>MessageQueue queue = new MessageQueue();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>Thread p1 = new Thread(new Produce(queue));</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>Thread p2 = new Thread(new Produce(queue));</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>Thread p3 = new Thread(new Produce(queue));</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>Thread p4 = new Thread(new Produce(queue));</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>Thread c1 = new Thread(new Consume(queue));</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>Thread c2 = new Thread(new Consume(queue));</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>p1.start();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>p2.start();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>p3.start();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>p4.start();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>c1.start();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>c2.start();</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span></div>
<div>}</div>
</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public void setName(String name) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>this.name = name;</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div>}</div>
</div>
<div><br />
</div>
<img src ="http://www.blogjava.net/yuyee/aggbug/336643.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yuyee/" target="_blank">羔羊</a> 2010-11-01 00:47 <a href="http://www.blogjava.net/yuyee/archive/2010/11/01/336643.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ReentrantReadWriteLock读写锁</title><link>http://www.blogjava.net/yuyee/archive/2010/10/31/336640.html</link><dc:creator>羔羊</dc:creator><author>羔羊</author><pubDate>Sun, 31 Oct 2010 15:31:00 GMT</pubDate><guid>http://www.blogjava.net/yuyee/archive/2010/10/31/336640.html</guid><description><![CDATA[public class <strong>ReentrantReadWriteLock&nbsp;</strong>extends <a title="java.lang 中的类" href="">Object</a>&nbsp;implements <a title="="">Object</a>&nbsp;implements <a title="java.util.concurrent.locks 中的接口" href="">ReadWriteLock</a>, <a title="java.io 中的接口" href="">Serializable</a>
<div>1.可重入，可重入的意思当前线程已获该锁，还可以再获取，但是读写锁里，WriteLock可以获取ReadLock,但是ReadLock不能获取WriteLock</div>
<div>2.WriteLock可以降级为ReadLock,意思是：先获取WriteLock,在获取ReadLock,释放WriteLock,这时候线程就将keep ReadLock,但是如果ReadLock想要升级为WriteLock，则不可能，因为根据读写锁的可重入特性，ReadLock排斥所有WriteLock,也就是(1)特性</div>
<div>3.ReadLock可以被多个线程持有并在作用时排斥任何WriteLock,而WriteLock隔离性比ReadLock高，它是完全的排斥，根据这一特性，读写锁适合高频率读，但不适合高频率写</div>
<div>4.不管是ReadLock,WriteLock都支持Interrupt</div>
<div>5.WriteLock支持Condition,但是ReadLock不支持Condition,将抛出<code>UnsupportedOperationException</code>。</div>
<div>下面是个小例子：</div>
<div><br />
</div>
<div><br />
</div>
<div>
<div>package com.google.study;</div>
<div><br />
</div>
<div>import java.util.Map;</div>
<div>import java.util.concurrent.ConcurrentHashMap;</div>
<div>import java.util.concurrent.locks.ReentrantReadWriteLock;</div>
<div>import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;</div>
<div>import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;</div>
<div><br />
</div>
<div>public class ReentrantLockStudy {</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private Map&lt;Integer, Result&gt; map = new ConcurrentHashMap&lt;Integer, Result&gt;();</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private final WriteLock writeLock = lock.writeLock();</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private final ReadLock readLock = lock.readLock();</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public Result get(Integer key) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>Result value = null;</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>readLock.lock();// 获取读锁</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>try {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>value = map.get(key);</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>if (value == null) {// 如果没有该结果</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>readLock.unlock();// 必须释放读锁</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>writeLock.lock();// 获取写锁</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>value = map.get(key);</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>if (value == null) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">					</span>value = getResult();</div>
<div><span class="Apple-tab-span" style="white-space:pre">					</span>map.put(key, value);</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>readLock.lock();// 重新降级为读锁</div>
<div><span class="Apple-tab-span" style="white-space:pre">				</span>writeLock.unlock();</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>} catch (Exception e) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>writeLock.unlock();</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>e.printStackTrace();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>} finally {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>readLock.unlock();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>return value;</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>public void put(Integer key, Result value) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>writeLock.lock();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>try {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>map.put(key, value);</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>} finally {</div>
<div><span class="Apple-tab-span" style="white-space:pre">			</span>writeLock.unlock();</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private Result getResult() {</div>
<div><span class="Apple-tab-span" style="white-space:pre">		</span>return new Result();</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>private static class Result {</div>
<div><br />
</div>
<div><span class="Apple-tab-span" style="white-space:pre">	</span>}</div>
<div>}</div>
</div>
<div><br />
</div>
<img src ="http://www.blogjava.net/yuyee/aggbug/336640.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yuyee/" target="_blank">羔羊</a> 2010-10-31 23:31 <a href="http://www.blogjava.net/yuyee/archive/2010/10/31/336640.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>