Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中的无锁优先级队列#_C#_.net_Priority Queue - Fatal编程技术网

C# C语言中的无锁优先级队列#

C# C语言中的无锁优先级队列#,c#,.net,priority-queue,C#,.net,Priority Queue,我最近一直在搜索有关如何在C#中构造无锁优先级队列的信息。我甚至还没有找到任何语言的实现,也没有关于这个问题的像样的文件。我发现有几篇论文似乎是副本,或者至少引用了一篇论文,而这篇论文实际上并不是无锁优先级队列上的论文,尽管它的名字是;事实上,这是一篇关于使用细粒度锁的优先级队列的论文 我从其他地方收到的回复包括“使用单个线程”、“不需要它就可以无锁”和“这是不可能的”。这三个回答都是错误的 如果有人知道这方面的信息,我将不胜感激。。请参阅第15章-优先级队列。这本书是用Java编写的,但可以很

我最近一直在搜索有关如何在C#中构造无锁优先级队列的信息。我甚至还没有找到任何语言的实现,也没有关于这个问题的像样的文件。我发现有几篇论文似乎是副本,或者至少引用了一篇论文,而这篇论文实际上并不是无锁优先级队列上的论文,尽管它的名字是;事实上,这是一篇关于使用细粒度锁的优先级队列的论文

我从其他地方收到的回复包括“使用单个线程”、“不需要它就可以无锁”和“这是不可能的”。这三个回答都是错误的

如果有人知道这方面的信息,我将不胜感激。

。请参阅第15章-优先级队列。这本书是用Java编写的,但可以很容易地翻译成C语言,因为它们都有GC(这对本书中的大多数实现都很重要)。

一般来说,这是一个很好的例子

但是,如果您真的想编写这种代码,我建议您从中获取一个页面,基本上,您将实现队列,但不是让对队列进行修改的所有函数修改您调用该方法的实例,而是让这些方法返回队列的全新实例

这在语义上类似于
System.String
用于维护不变性的模式;所有操作都会返回一个新的
系统字符串
,原始字符串不会被修改

这样做的结果是,您必须重新分配每次调用返回的引用。因为引用的赋值是原子操作,所以不需要担心线程安全;您可以保证读/写是原子的

然而,这将导致最后的胜利局面;可能对队列进行了多次修改,但只有最后一次分配将保持不变,从而丢失了队列中的其他插入


这可能是可以接受的;如果没有,则必须在分配和读取引用时使用同步。您仍然会有一个无锁优先级队列,但是如果您担心线程安全和维护操作的完整性,那么除了将同步问题转移到数据结构之外,您什么也没做(几乎所有情况下,这都是一件好事,因为它为您提供了细粒度的显式控制).

你怎么知道他们都错了?@soandos使用单线程违背了此数据结构的目的,如果我不需要它是无锁的,那么我就不会问这个问题,这并不是不可能的,因为以前已经这样做过。对于带有锁定的优先级队列来说,您的要求是什么?细粒度的锁是您想要的,我认为100%无锁是不可能的。@Snoopy幸运的是,我看到了无锁优先级队列的实现。细粒度锁只能在二进制堆中作为优先级队列使用,并锁定希望访问的每个子级。我已经做了这样一个实现,但它远远不够理想,因此我追求的是完全无锁的东西。该示例在其实现中使用了测试和设置指令,这一特性在C#中是不可用的,没有对执行引擎(.NET,Mono,…)进行特定添加。NET不提供这样的功能,很遗憾。@JNZ没有联锁。CompareeExchange您要找的是什么?@MerickOWA没有,因为这是比较和交换,而不是测试和设置或测试、测试和设置。不幸的是,它们根本不同,无法相互融合;我们需要执行级别控制。如果测试和设置意味着。。。(如果location==0,那么location=1,返回true,否则返回false)作为单个原子指令,为什么Interlock.CompareExchange(ref-location,0,1)==0与test和set不一样?您能否详细说明关于无锁优先级队列的实现细节?我不太明白这在实践中是如何工作的,但我理解它可能适用的背后的理论。@JNZ:假设
PriorityQueue
有一个
Push
方法。它不具有
void
返回类型,而是返回
PriorityQueue
的新实例;返回的实例将包含原始队列中的项,以及推送到该实例上的新项。这在没有锁的情况下工作,因为它涉及到对原始对象的读取操作,而对新对象的写入操作发生在构造函数中,这将始终是线程安全的。所有可变操作都将返回一个新实例。您只需确保跟踪新的引用即可。@casperOne好的,那么让我看看是否有这个权利。我遵循
Pop
方法的工作原理。
Push
方法将接收一个项目并返回一个新的
PriorityQueue
,其中包含该项目。不可变的
PriorityQueue
singleton将在原子操作中用刚刚返回的引用更新其引用。应该是这样的吗?如果两个或多个线程同时弹出怎么办?他们不是都会把同一件东西放出来吗?@JNZ:是的,没错。请记住,
Pop
方法实际上不会删除任何内容,而是返回一个新的
PriorityQueue
,并删除该项。Eric Lippert博客的链接展示了如何为许多数据结构实现这一点。