Statck类中pop方法与WeakOrderedQueue 中的add 方法之间的同步问题?
来源:10-10 异线程收割对象

triump
2019-09-04
请问下,老师:
- 在 add 方法中, 会修改 weakorderqueue对象的tail 指针与 link 对象 的next 指针。
- 在Stack 类中的pop 方法中,会读取上面的tail 与next 指针
- 以上操作是在两个不同的线程中执行, 为什么不在Link 类中的next 域加上volatile ,在WeakOrderQueue 中的tail 域加上volatile ? 怎么解释?
- 难道是因为 作者在add 方法中的最后一行调用了这个方法:
// we lazy set to ensure that setting stack to null appears before we unnull it in the owning thread;
// this also means we guarantee visibility of an element in the queue if we see the index updated
tail.lazySet(writeIndex + 1); - 作者对 Recycler 的设计有很多地方值得参考,为了避免加锁,才设计了这样队列式的WeakOrderQueue数据结构,而且保证其head指针可以指向至少一个 Link 对象节点。Link 里又放了一个数组,批量分配空间,避免自身管理数据结构的内存分配开销。并充分利用了ThreadLocal ,首先Stack 是对象生成线程局部的,而且将每个WeakOrderQueue 节点 与对应的Stack 又放在回收线程的ThreadLocal 的map 里,这样每个回收线程互不影响add 操作,只是在new 一个WeakOrederQueue 节点时 并插入到Stack 的头部时候,加了锁,防止写写冲突, 而对于需要遍历WeakOrderQueue 链表的 读线程,不需要加锁,只需要把head 声明成volatile 的. 这时我的理解
- 我的问题主要在第3点
写回答
1回答
-
闪电侠
2019-09-05
这个问题提的非常棒,你的理解也非常正确,这边为了防止线程冲突,用了很多 FastThreadLocal 变量,使得每个线程都有自己局部的 Stack,互不影响,然后每个 Stack 中的元素有可能被其他线程进行回收,每个其他线程都会有一个 WeakOrderQueue 与个 Stack 关联,然后这些 WeakOrderQueue 通过以 head 为头的节点串起来,因此,多个线程的并发关系,只有可能发生的 head 节点上,每个线程维护的 WeakOrderQueue 都是相互独立的,不会受到影响;
012019-09-05
相似问题