我正在使用Hazard指针,以便在C中实现无锁链接列表。 除了各种基本队列和堆栈之外,我找不到任何示例代码。 问题是我需要遍历列表,所以我的问题是我是否可以在分配后更改危险指针的值。 例如:
t←Top
while(true) {
if t=null then
return null
*hp←t
if Top!=t then
continue
...
t←(t→next) //after this instruction pointer t will be still protected?
}
答案 0 :(得分:2)
最后,我根据the original paper结束了我自己版本的危险指针(HP)。我的问题的答案是否定的, t 不再安全使用。原因是,HP工作的方式, * hp 在您将其声明为危险指针时保护 t 所指向的节点,因此 t < / em>移动到下一个节点,HP机制继续保护前一个节点。在安全使用之前,我必须将新值重新分配给 * hp 。
另外,在论文的例子中,它并不明确,但是当你使用了危险指针时,你必须释放它。这意味着,将 * hp 恢复为原始状态( NULL )。这样,如果另一个线程想要删除(退出)这个节点,它就不会被视为被使用。
在上面的示例中,我必须在离开方法之前释放 * hp 。在循环内部没有必要,因为我覆盖了相同的* hp位置(* hp←t),因此前一个节点不再受保护。
答案 1 :(得分:1)
当您只遍历列表时,不需要危险指针。当不同的线程从同一资源读取和写入时,会发生危险(特别是,当资源的值更改为某个值然后返回其原始值时,危险指针将克服ABA问题,这会使注意到更改变得困难) 。通过遍历,您只需阅读,因此无需使用危险指示。
顺便说一句,在我看来,您必须将if Top=t
更改为if Top!=t
,以便在没有危险的情况下继续执行您的代码。请注意continue
返回循环的开头。此外,您的整个代码应该是一个while(true)循环。
您可以在此处阅读有关危险指针的更多信息http://www.drdobbs.com/lock-free-data-structures-with-hazard-po/184401890,或仅通过Google搜索!
编辑您需要提供插入和删除功能的代码。简而言之,您提到的代码部分在执行t←(t→next)
后最终成为无限循环,因为Top!= t将在之后成立。
你需要做什么,而不是检查顶部,是检查它以前捕获的值。同样,它取决于您对其他方法的实现,但您可能希望实现类似于Tim Harris algorithm的东西,它使用两阶段删除(1标记和2释放节点)。然后,当您遍历列表时,您还需要检查标记的节点。在http://www.research.ibm.com/people/m/michael/ieeetpds-2004.pdf的图9中还有一个双向链表的实现,其中有一个find方法,您可以将其用作实现的基础。希望这可以帮助。