![](https://csdnimg.cn/release/download_crawler_static/87912993/bg7.jpg)
reasonml
复制代码
//更改 Node 中的数据域 itemboolean casItem(E cmp, E val) { return
UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);}//更改 Node 中
的指针域 nextvoid lazySetNext(Node<E> val)
{ UNSAFE.putOrderedObject(this, nextOffset, val);}//更改 Node 中的指
针域 nextboolean casNext(Node<E> cmp, Node<E> val) { return
UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);}
可以看出这些方法实际上是通过调用 UNSAFE 实例的方法,UNSAFE 为
sun.misc.Unsafe 类,该类是 hotspot 底层方法,目前为止了解即可,知道 CAS
的操作归根结底是由该类提供就好。
2.offer 方法
对一个队列来说,插入满足 FIFO 特性,插入元素总是在队列最末尾的地方进行
插入,而取(移除)元素总是从队列的队头。所有要想能够彻底弄懂
ConcurrentLinkedQueue 自然而然是从 offer 方法和 poll 方法开始。那么为了能
够理解 offer 方法,采用 debug 的方式来一行一行的看代码走。另外,在看多
线程的代码时,可采用这样的思维方式:
单个线程 offer > 多个线程 offer > 部分线程 offer,部分线程
poll ----offer 的速度快于 poll --------队列长度会越来越长,
由于 offer 节点总是在对队列队尾,而 poll 节点总是在队列对头,
也就是说 offer 线程和 poll 线程两者并无“交集”,也就是说两
类线程间并不会相互影响,这种情况站在相对速率的角度来看,也
就是一个"单线程 offer" ----offer 的速度慢于 poll
--------poll 的相对速率快于 offer,也就是队头删的速度要快于
队尾添加节点的速度,导致的结果就是队列长度会越来越短,而
offer 线程和 poll 线程就会出现“交集”,即那一时刻就可以称
之为 offer 线程和 poll 线程同时操作的节点为 临界点 ,且在该节
点 offer 线程和 poll 线程必定相互影响。根据在临界点时
offer 和 poll 发生的相对顺序又可从两个角度去思考:1. 执行顺
序为 offer-->poll-->offer,即表现为当 offer 线程在 Node1 后
插入 Node2 时,此时 poll 线程已经将 Node1 删除,这种情况很
显然需要在 offer 方法中考虑; 2.执行顺序可能为:
poll-->offer-->poll,即表现为当 poll 线程准备删除的节点(队
列为空队列),此时 offer 线程插入一个节点使得队列变为非空队
列
先看这么一段代码:
lasso
复制代码