关于java线程(4)----JUC之 原子操作
?
?
?
pool-1-thread-1execute successful! 100000
pool-1-thread-3execute successful! 100002
pool-1-thread-4 execute?failed!
pool-1-thread-2execute successful! 100001
pool-1-thread-8execute successful! 100003
pool-1-thread-9 execute?failed!
pool-1-thread-5 execute?failed!
pool-1-thread-7execute successful! 100004
pool-1-thread-10 execute?failed!
boolean
?boolean
?int
?使用 Treiber 算法的非阻塞堆栈
<!--EndFragment-->
?
?<!--[endif]-->首先插入一个元素涉及两个指针更新,这两个更新都是通过 CAS 进行的:从队列当前的最后节点(C)链接到新节点,并把尾指针移动到新的最后一个节点—)。如果第一步失败,那么队列的状态不变,插入线程会继续重试,直到成功。一旦操作成功,插入被当成生效,其他线程就可以看到修改。还需要把尾指针移动到新节点的位置上,但是这项工作可以看成是 “清理工作”,因为任何处在这种情况下的线程都可以判断出是否需要这种清理,也知道如何进行清理。队列总是处于两种状态之一:正常状态(或称静止状态,图 1?和?图 3)或中间状态(图 2)。在插入操作之前和第二个 CAS—)成功之后,队列处在静止状态;在第一个 CAS(C)成功之后,队列处在中间状态。在静止状态时,尾指针指向的链接节点的 next 字段总为 null,而在中间状态时,这个字段为非 null。任何线程通过比较?
tail.next?是否为 null,就可以判断出队列的状态,这是让线程可以帮助其他线程 “完成” 操作的关键。图 2.处在插入中间状态的队列,在新元素插入之后,尾指针更新之前
<!--[if !supportLineBreakNewLine]-->
?<!--[endif]-->
?<!--[endif]-->public class LinkedQueue <E> {?
总结CAS操作是并发包的核心,前面已经说过,如果将Lock、CountDownLatch、FutureTask等最后都看成是依赖“状态”的操作,“状态”允许的情况下ok,否则挂起,那么对于“状态”的操作就需要同步的或者是原子的,因此原子操作就是这些类的核心,或者说前提条件!
?
?
?
?
?
