java - AbstractQueuedSynchronizer中CAS的疑惑
问题描述
这段代码是AQS框架中将当前节点入队的操作。
Node pred = tail;if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) {pred.next = node;return node; }}
上面代码中pred被赋值为尾节点,node为当前节点。我理解的将新节点插入链表尾处的逻辑应当如下:node.prev = pred; node节点的前驱指向尾节点pred.next = node; 将尾节点的后继设置为当前节点tail = node; 将node节点设置为尾节点对于上面代码我的疑问如下:如果尾节点不为空,node节点的前驱会指向尾节点,然后调用CAS交换pred和node的值。此时pred(即tail)的值应该已经是当前节点node的值了,再执行pred.next=node是什么意思呢,这是否存在逻辑问题?
问题解答
回答1:TZ可能对compareAndSetTail的理解有误。
private final boolean compareAndSetTail(Node expect, Node update) {return unsafe.compareAndSwapObject(this, tailOffset, expect, update); }
在AbstractQueuedSynchronizer的tailOffset位置比较pred的值和期望的node值,如果相同则更新tailOffset位置的值。
static { tailOffset = unsafe.objectFieldOffset (AbstractQueuedSynchronizer.class.getDeclaredField('tail')); ...}
compareAndSetTail(pred, node) 这句代码执行完成之后,被修改只是对象AbstractQueuedSynchronizer的tailOffset的值,也就是成员变量tail的值,对于pred的值没有任何影响。至于双向链表,尾部插入,逻辑上没有问题。
回答2:这个设计是一个双向链表.B.prev == AA.next == B
compareAndSetTail 设置成功只是将 tail 更新为当前node. pred.next 是将上一个尾部节点的next设置为当前node这逻辑不存在问题.
相关文章:
1. $fields = $values = [];这条代码一直定义不了,一直报错,老师的源码也是被报错的,执行不了,请问该怎么解决这个问题2. python - 求一个在def中可以实现调用本def满足特定条件continue效果的方法(标题说不太清楚,请见题内描述)3. java - mybatis怎么实现在数据库中有就修改,没有就添加4. MYSQL新建用户设置可以远程访问的问题5. node.js - nodejs和前端JavaScript 字符串处理结果不一样是什么原因?6. angular.js - angularjs的自定义过滤器如何给文字加颜色?7. javascript - 用表单提交两个时间段请求后台返回对应数据时出现的一些问题!8. docker-compose中volumes的问题9. mysql - SQL操作时间的函数?10. docker api 开发的端口怎么获取?
![$fields = $values = [];这条代码一直定义不了,一直报错,老师的源码也是被报错的,执行不了,请问该怎么解决这个问题](http://www.haobala.com/attached/image/news/202205/093622cb60.png)