Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.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#_Multithreading_Thread Safety_Locking_Semaphore - Fatal编程技术网

C# 使用锁是否比使用本地(单个应用程序)信号量具有更好的性能?

C# 使用锁是否比使用本地(单个应用程序)信号量具有更好的性能?,c#,multithreading,thread-safety,locking,semaphore,C#,Multithreading,Thread Safety,Locking,Semaphore,使用锁是否比使用本地(单个应用程序)信号量具有更好的性能 我从msdn上读到这个博客: 我不喜欢他们对这个问题的解决方案,因为队列中总是剩下20个元素 因此,我考虑使用一个只在我的应用程序中可用的“信号量”(我只是不在构造函数中命名),但我不知道它会如何影响应用程序的性能 有人知道这是否会影响性能吗?使用锁而不是“信号量”的其他注意事项是什么?lock(obj)与Monitor.Enter(obj)相同;锁基本上是一元信号量。如果同一个ressource(N)有多个实例,则使用初始化值为N的信号

使用锁是否比使用本地(单个应用程序)信号量具有更好的性能

我从msdn上读到这个博客:

我不喜欢他们对这个问题的解决方案,因为队列中总是剩下20个元素

因此,我考虑使用一个只在我的应用程序中可用的“信号量”(我只是不在构造函数中命名),但我不知道它会如何影响应用程序的性能

有人知道这是否会影响性能吗?使用锁而不是“信号量”的其他注意事项是什么?

lock(obj)与Monitor.Enter(obj)相同;锁基本上是一元信号量。如果同一个ressource(N)有多个实例,则使用初始化值为N的信号量。锁主要用于确保代码段不会由两个线程同时执行

因此,可以使用初始化值为1的信号量实现锁。我想显示器。回车在这里更有效,但我没有这方面的真实信息。测试在这里会有帮助。这里有一个关于表现的例子

对于您的问题,阻塞队列将是解决方案。(生产者消费者)我建议非常好的SO线程


这是另一个很好的信息来源。

MSDN文章中的解决方案有一个bug,如果生产者在消费者处理从队列中检索的最后一个项目时连续两次调用SetEvent,您将错过一个事件

请参阅本文,了解使用Monitor的不同实现:


一般来说:如果您的使用者线程能够足够快地处理每个数据项,那么内核模式转换将产生一点开销(可能很大)。在这种情况下,在等待信号量之前旋转一段时间的用户模式包装器将避免一些开销


监视器(带互斥+条件变量)可能实现也可能不实现旋转。那篇MSDN文章的实现没有这样做,所以在本例中,性能没有真正的区别。无论如何,除非您使用的是无锁队列,否则您仍然必须锁定才能将项目出列。

TLDR我刚刚运行了自己的基准测试,在我的设置中,
lock
的运行速度几乎是
信号量lim(1)
的两倍

规格

  • .NET核心
    2.1.5
  • 视窗10
  • 2个物理核(4个逻辑核)@
    2.5 GHz
测试

我试着并行运行2、4和6个
任务
s,每个任务执行1M个访问锁的操作,执行一个简单的操作并释放锁。代码如下所示:

await semaphoreSlim1.WaitAsync();
// other case: lock(obj) {...}

if(1 + 1 == 2)
{
    count++;
}        

semaphoreSlim1.Release();
结果 对于每种情况,
lock
的运行速度几乎是
SemaphoreSlim(1)
的两倍(例如
205ms
vs
390ms
,使用
6
并行任务)


请注意,我并不声称它在无限多的其他设置上更快。

lock和semaphore slim是完全不同的,我会避免混合使用它们。如果您正确使用异步,那么信号量lim是好的

如果您的锁围绕着一个wait调用,请记住,在等待之后开始运行的线程不一定与调用它的线程相同。它可能是同一个线程上下文,但这是另一回事


另外,如果您的方法返回一个任务,并且您的方法包含一个锁,那么您将发现用于运行该任务的一个线程池线程将被阻塞,直到锁被释放为止,因此,您可能会在程序中的其他地方饿死任意任务,这些任务需要运行的线程。

谢谢您的回答,但这并不是真正回答我的问题:)我添加了一个指向另一个线程的链接,以控制性能。这对您有帮助吗?请注意:sempahore(在操作系统级别)使用速度快得多的硬件锁,因此使用信号量实现锁似乎有点适得其反。考虑到ie可重入性,锁实际上不同于信号量:锁是可重入的,而信号量不是。信号量可以在其他线程中释放。谢谢你的回答,但是你的帖子有一个不同的bug。。消费者中检查队列大小是否不等于零的检查有问题。示例:队列包含一个产品。两个客户端同时执行检查并进入while循环,一个锁定监视器,另一个正在等待。第一个用户消耗产品(因此没有产品了!),然后退出监视器。现在,第二个队列进入监视器,并尝试将一个空队列排出队列。。致命错误。实际上,当第二个使用者在内部while循环中被唤醒并重新获得锁时,它将继续while循环并检查队列是否为空,然后再决定继续并从队列中退出,这样您就不会得到刚才提到的错误。但是,正如作者所提到的,它只是一个部分实现,没有对出列项做任何操作。它内置于.NET 4.0中,开箱即用。相反,我们应该比较lock和SpinLock。有关更多信息,请在此处查找“PerformanceCharacteristicsOfSyncPrimitions.pdf”:将优化
if
,因此它没有任何用处。我还将使用常规的
Wait
而不是
WaitAsync
,因为这可能会导致线程切换。这是我们不想测量的。C#language引用明确指出“不能在lock语句体中使用await运算符。”@AndersEmil的观点很好,但锁定对象不需要使用lock语句。您可能正在使用System.Threading.Monitor。。。在这种情况下,将异步和锁定混合在一起可能会有不好的结果,而使用信号量LIM可能会有更好的结果。