是Interlocked.CompareExchange真的比简单的锁快吗? [英] Is Interlocked.CompareExchange really faster than a simple lock?

查看:399
本文介绍了是Interlocked.CompareExchange真的比简单的锁快吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了.NET 3.5的ConcurrentDictionary实现(很抱歉,我现在可以找到链接),该实现使用此方法进行锁定:

I came across a ConcurrentDictionary implementation for .NET 3.5 (I'm so sorry I could find the link right now) that uses this approach for locking:

var current = Thread.CurrentThread.ManagedThreadId;
while (Interlocked.CompareExchange(ref owner, current, 0) != current) { }

// PROCESS SOMETHING HERE

if (current != Interlocked.Exchange(ref owner, 0))
        throw new UnauthorizedAccessException("Thread had access to cache even though it shouldn't have.");

代替传统的lock:

lock(lockObject)
{
    // PROCESS SOMETHING HERE
}

问题是:这样做有什么真正的理由吗?是更快还是有一些隐藏的好处?

The question is: Is there any real reason for doing this? Is it faster or have some hidden benefit?

PS:我知道在.NET的某些最新版本中有一个ConcurrentDictionary,但我不能用于旧项目.

PS: I know there's a ConcurrentDictionary in some latest version of .NET but I can't use for a legacy project.

修改:

在我的特定情况下,我正在做的只是以一种线程安全的方式操纵内部Dictionary类.

In my specific case, what I'm doing is just manipulating an internal Dictionary class in such a way that it's thread safe.

示例:

public bool RemoveItem(TKey key)
{
    // open lock
    var current = Thread.CurrentThread.ManagedThreadId;
    while (Interlocked.CompareExchange(ref owner, current, 0) != current) { }


    // real processing starts here (entries is a regular `Dictionary` class.
    var found = entries.Remove(key);


    // verify lock
    if (current != Interlocked.Exchange(ref owner, 0))
        throw new UnauthorizedAccessException("Thread had access to cache even though it shouldn't have.");
    return found;
}

正如@doctorlove建议的那样,这是代码: https://github.com/miensol/SimpleConfigSections/blob/master/SimpleConfigSections/Cache.cs

As @doctorlove suggested, this is the code: https://github.com/miensol/SimpleConfigSections/blob/master/SimpleConfigSections/Cache.cs

推荐答案

如果此处有处理"引发异常,您的CompareExchange示例代码不会释放该锁.

Your CompareExchange sample code doesn't release the lock if an exception is thrown by "PROCESS SOMETHING HERE".

由于这个原因,以及更简单,更易读的代码,我希望使用lock语句.

For this reason as well as the simpler, more readable code, I would prefer the lock statement.

您可以尝试/最终解决问题,但这会使代码更加难看.

You could rectify the problem with a try/finally, but this makes the code even uglier.

链接的ConcurrentDictionary实现有一个错误:如果调用方传递了null键,它将无法释放锁,从而可能导致其他线程无限期地旋转.

The linked ConcurrentDictionary implementation has a bug: it will fail to release the lock if the caller passes a null key, potentially leaving other threads spinning indefinitely.

关于效率,您的CompareExchange版本本质上是 Spinlock ,如果使用线程,则可以提高效率仅在短期内被阻止.但是插入托管字典可能会花费相对较长的时间,因为可能需要调整字典的大小.因此,恕我直言,这不是自旋锁的理想选择-这可能很浪费,尤其是在单处理器系统上.

As for efficiency, your CompareExchange version is essentially a Spinlock, which can be efficient if threads are only likely to be blocked for short periods. But inserting into a managed dictionary can take a relatively long time, since it may be necessary to resize the dictionary. Therefore, IMHO, this isn't a good candidate for a spinlock - which can be wasteful, especially on single-processor system.

这篇关于是Interlocked.CompareExchange真的比简单的锁快吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆