你好我试着写一个无锁列表我得到了添加部分工作它想但是从列表中提取对象的代码不能正常工作:(
那么列表不是正常列表..我有接口IWorkItem
interface IWorkItem
{
DateTime ExecuteTime { get; }
bool Cancelled { get; }
void Execute(DateTime now);
}
并且我有一个列表,我可以添加这个:P和idear是我运行Get();在列表上它应该循环它,直到它找到
的IWorkItemIf (item.ExecuteTime < DateTime.Now)
并将其从列表中删除并返回.. 我已经在我的双核cpu上运行了许多线程的测试,看起来Add工作到目前为止从未失败过,但Get函数丢失了一些工作项,其中一些我没有想法的错误......
ps如果我得到这个工作任何人都可以免费使用代码:)你有什么办法,但我不明白它的问题:P
代码在这里http://www.easy-share.com/1903474734/LinkedList.zip,如果你试图运行它,你会发现它有时候无法获得与列表中放置的工作项一样多的工作项......
编辑:我有一个无锁列表工作它比使用lock(obj)语句更快但我有一个使用Interlocked的锁定对象仍然超出无锁列表,我将尝试制作一个无锁的arraylist和如果我得到相同的结果,当我完成生病时上传结果在这里..
答案 0 :(得分:5)
问题在于你的算法:考虑这一系列事件:
线程1调用list.Add(workItem1)
,完全完成。
状态是:
first=workItem1, workItem1.next = null
然后第1个线程调用list.Add(workItem2)
并在第二个Replace
之前到达该地点(您有评论“// let try”)。
状态是:
first=workItem1, workItem1.next = null, nextItem=workItem1
此时线程2接管并调用list.Get()
。假设workItem1
的executionTime现在是,所以调用成功并返回workItem1
。
此状态为:
first = null, workItem1.next = null
(在另一个帖子中,nextItem
仍为workItem1
)。
现在我们回到第一个帖子,它通过设置Add()
来完成workItem1.next:=workItem2
。
如果我们现在致电list.Get()
,即使null
成功完成,我们也会获得Add()
。
您应该查找一个真正的同行评审的无锁链表算法。我认为标准的是John Valois的this。有一个C ++实现here。关于无锁优先级队列的This文章也可能有用。
答案 1 :(得分:1)
所以你确定它需要无锁吗?根据您的工作量,非阻塞解决方案有时会变慢。请查看此MSDN article以获取更多信息。同样证明无锁数据结构是正确的可能非常困难。
答案 2 :(得分:1)
您可以使用数据结构的时间戳协议,从数据库世界中镜像此示例:
但请注意,每个项目都需要读写时间戳,并且请务必明确遵循算法规则。
我认为,在链表上实现这一点还有一些额外的困难。数据库示例适用于您知道所需数组索引的向量。但是,在链表中,您可能需要沿着指针向下走 - 当您搜索时,列表的结构可能会发生变化!我想你可以通过某种细微差别解决这个问题(或者如果你只是想要遍历“新”列表,不做任何事情),但它会带来问题。尝试解决它而不引入一些回滚条件,使其比锁定列表更糟糕!
答案 3 :(得分:0)
我绝不是这方面的专家,但据我所知,你需要在IWorkItem volatile的实现中创建ExecutionTime-field(当然它可能已经是那个)或者插入一个{ {3}}在您设置ExecutionTime之后或在您阅读之前。{/ p>