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

Adi*_*be7 4 c# multithreading semaphore locking thread-safety

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

我从msdn阅读此博客:msdn上的生产者消费者解决方案

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

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

有谁知道会影响性能吗?使用锁而不是“信号量”的其他考虑是什么?

sch*_*tbi 9

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

因此,可以使用初始化值为 1 的信号量来实现锁。我猜这里 Monitor.Enter 的性能更高,但我没有关于它的真实信息。在这里进行测试会有所帮助。这是一个处理性能的SO 线程

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

这是关于可重用并行数据结构的另一个很好的信息来源。

  • 感谢您的回答,但它并没有真正回答我的问题:) (2认同)
  • 考虑到可重入性,锁实际上与信号量不同:锁是可重入的,而信号量则不是。然而,信号量可以在其他线程中释放。 (2认同)

edd*_*P23 6

TLDR我只是运行自己的基准测试,在我的设置中,它的lock运行速度几乎是的两倍SemaphoreSlim(1)

规格

  • .NET核心 2.1.5
  • Windows 10
  • 2个物理核心(4个逻辑)@2.5 GHz

测试

我尝试Task并行运行2,4和6 s,它们每个都执行1M的访问锁,微不足道的操作并释放它的操作。该代码如下所示:

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

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

semaphoreSlim1.Release();
Run Code Online (Sandbox Code Playgroud)

结果 对于每种情况,其lock运行速度几乎是其两倍SemaphoreSlim(1)(例如,205ms390ms使用6并行任务相比)。

请注意,我并没有声称在无限数量的其他设置下它会更快。

  • `if` 会被优化掉,所以它没有用。我还会使用常规的“Wait”而不是“WaitAsync”,因为它有可能进行线程切换。我们不想测量。 (8认同)