问题是这样的:
我有一个500个指针的数组,指向双链表中的500个元素。有10个线程并行运行。每个线程运行50个循环,并尝试释放列表中的一些元素。
列表已排序(包含简单整数),并且还有10个其他线程并行运行,搜索包含特定整数的节点并访问此节点中的其他卫星数据。所以节点就像:
struct node
{
int key; // Key used to search this nodes
int x,y,z; // Satellite data
struct node *prev;
struct node *right;
};
如果我只是在搜索/删除之前锁定列表,问题很容易解决。但这太粗糙了。如何同步这些线程以便我可以实现更好的并发性?
编辑:
答案 0 :(得分:3)
您可以使用CompareAndSwap操作考虑无锁链接列表。
答案 1 :(得分:2)
我可以想到一些不涉及全局锁定的广泛方法,并应该允许一定程度的前进:
当删除线程识别其受害者时,将其标记为已删除但将其保留在原位。 当搜索线程遇到具有此删除标记的节点时,它只会忽略它。
在标记删除的节点之后,您需要发出写入/释放障碍,并在检查值之前发出获取障碍:您需要特定于平台的,特定于编译器的扩展,否则您将编写这些障碍汇编
根据Peeyush的回答中的论文; CAS的类似平台或编译器特定要求,需要非常小心。诸如refcounts或危险指针之类的选项可以允许节点在没有人看到它时被真正删除。您可能会发现需要用short
索引替换prev / next指针,这些索引可以打包成一个单词供CAS工作:这意味着绑定节点数并将它们分配到数组中。
另请注意,尽管每个线程都应该能够在这种方案上取得进展,但由于同步要求,单个操作(例如,遍历到下一个节点)可能会变得更加昂贵。
答案 2 :(得分:0)
您需要锁定任何可以更改的数据。如果您要做很多工作,请在列表中为每个项目创建一个锁。线程必须锁定前一个,当前一个和下一个项目才能删除中间项目。确保始终以相同的顺序获取锁定以避免死锁。
其他删除线程和搜索线程必须等到删除对象并设置新链接。然后锁被释放,他们可以继续。