void try_reclaim(node* old_head)
{
if(threads_in_pop==1) // 1
{
node* nodes_to_delete=to_be_deleted.exchange(nullptr); // 2 声明“可删除”列表
if(!--threads_in_pop) // 3 是否只有一个线程调用pop()?
{
delete_nodes(nodes_to_delete); // 4
}
else if(nodes_to_delete) // 5
{
chain_pending_nodes(nodes_to_delete); // 6
}
delete old_head; // 7
}
else
{
chain_pending_node(old_head); // 8
--threads_in_pop;
}
}
```c++
//--------------------------------------------------------
在注释3处,假设此时的threads_in_pop为0了,但他也不能保证他的下一刻不为0啊,他为什么能删除这个待删除链表啊?
而且注释1和注释3不是冲突了嘛
在注释3处,假设此时的threads_in_pop为0了,但他也不能保证他的下一刻不为0啊,他为什么能删除这个待删除链表啊?
-
你大概没明白这个回收逻辑,nodes_to_delete 是属于线程的私有变量,threads_in_pop 为 0,意味着 nodes_to_delete 和任何其它线程都无关了,threads_in_pop 哪怕再增加100,也只与 to_be_deleted 有关,自然可安全删除。
-
但是如果 threads_in_pop 不为 0,意味着 to_be_deleted 可能回收了其它线程传出的 old_head,而这个 old_head 可能同时被很多个线程引用,并且进行解引用操作,此时 nodes_to_delete 与 to_be_deleted 交换,其节点中,就必然有被其它多个线程引用的资源,一旦删除,会发生各种意想不到的问题。
-
而且注释1和注释3不是冲突了嘛
-
注释1和注释3的意义完全不同,1 是说 pop 已经将 head 后移一位了,其 oldhead 只有这么一个引用,可安全删除。而 3 是说 nodes_to_delete 已经和所有其它线程切割关系,没有任何线程引用其节点,可以安全的将其删除了。
threads_in_pop应该是全局变量,要看to_be_deleted.exchange函数是否会修改这个全局变量值。否则确实3的 if判断多余了