C# 实现无锁队列(针对记录器组件)

C# 实现无锁队列(针对记录器组件),c#,.net,multithreading,concurrency,lockless,C#,.net,Multithreading,Concurrency,Lockless,我正在设计一个新的改进的记录器组件(.NET3.5,C#) 我想使用无锁实现 日志事件将从(可能)多个线程发送,尽管只有一个线程将实际输出到文件/其他存储介质 本质上,所有写入程序都是将其数据“排队”到某个队列中,由另一个进程(LogFileWriter)检索 这可以通过无锁方式实现吗?我在网上找不到有关此特定问题的直接参考。此无锁队列的实现可能会有所帮助,其中队列是用于将要出列的项目排队并由记录器写入的数据结构 您还可以查看.NET4的ConcurrentQueue 如果您发现在这种情况下

我正在设计一个新的改进的记录器组件(.NET3.5,C#)

我想使用无锁实现

日志事件将从(可能)多个线程发送,尽管只有一个线程将实际输出到文件/其他存储介质

本质上,所有写入程序都是将其数据“排队”到某个队列中,由另一个进程(LogFileWriter)检索


这可以通过无锁方式实现吗?我在网上找不到有关此特定问题的直接参考。

此无锁队列的实现可能会有所帮助,其中队列是用于将要出列的项目排队并由记录器写入的数据结构

您还可以查看.NET4的ConcurrentQueue


如果您发现在这种情况下使用锁的速度太慢,您会遇到更大的问题。在我的系统(2.0 GHz Core 2 Quad)上,一个锁在没有竞争的情况下大约需要75纳秒。当然,当它被争夺时,它将需要更长的时间。但是,由于锁只是保护对
入队
出队
的调用,因此日志写入的总时间不太可能超过75纳秒

如果锁是一个问题——也就是说,如果您发现线程排列在锁后面,并导致应用程序中明显的速度减慢——那么创建无锁队列不太可能有多大帮助。为什么?因为如果您真的要在日志中写入那么多内容,那么无锁阻塞队列将很快填满,您将受限于I/O子系统的速度


我有一个多线程应用程序,它每秒将200个日志条目写入一个受简单锁保护的
队列。我从未注意到任何明显的锁争用,而且处理速度丝毫没有减慢。与做其他事情所需的时间相比,这75 ns相形见绌。

有很多不同的无锁队列实现

我自己的at使用了一种简单的方法,并且是开源的,因此您可以在必要时对其进行调整


ConcurrentQueue
也是无锁的,可能可以很好地满足大多数目的,尽管Ariadne中有几个成员支持其他操作(例如将整个内容的枚举作为原子操作出列,这允许单个使用者更快地枚举).

。可能是因为没有需求。大多数日志记录活动的一端是断断续续的日志,另一端是缓慢的磁盘。对于这种功能,一个锁定的、内核管理的队列是最有效的。在你的应用程序中使用无锁队列有什么特别的原因吗?我不确定大多数日志记录者使用锁定,即使可能不使用它。我的要求是高性能,这意味着尽快释放调用记录器的线程。在这种情况下,抓锁似乎是一种浪费。我同意汉斯的观点。有很好的机会比国产系统更快,并且在开发和调试过程中花费更少的时间才能正常运行。关于性能记录器,请使用DateTime.UtcNow。它比DateTime快得多。现在,在分析我的应用程序时,对日志线程来说是一个重大的打击。我使用log4net。@liortal-允许多个生产者的无锁队列实现非常简单。然后还有一个问题,即如何向使用者/记录器线程发出信号,表明已添加了一个新条目,以便它可以从日志中检索该条目。我会使用信号灯,但还有其他条件。无论您使用什么,这可能意味着内核调用向记录器发送信号。唯一可以以无锁方式避免内核调用的路径是,如果生产者在队列上使用自旋锁并确定队列计数不是零。如果你能做到这一点,你就不需要任何帮助!谢谢,我会查出来的。您知道这是否适用于所有不同的场景(例如:多个读者、多个作者、单个读者、多个作者等)?我知道这些场景,但没有机会使用它们,因此无法确定地回答。在并发集合的情况下,由于它们与.net的并行添加一起出现,我认为多个读者/作者是目的所在。在你的情况下,你可能需要多个作者,一个读者,这不应该让排队的人负担过重。您有一个生产者/消费者模式,因此使用ConcurrentQueue的BlockingCollection就可以做到这一点。是的,它适用于不同的场景。