如何让阅读这种情况下原始的线程安全的无锁? [英] How to make reading this instance primitive thread-safe without locking?

查看:204
本文介绍了如何让阅读这种情况下原始的线程安全的无锁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

与下面类的问题是阅读时 myThreadSafe.Value 它可能不会返回最先进的最新值。

The problem with the below class is when reading myThreadSafe.Value it may not return the most up-to-date value.

public class ThreadSafe
{   
    private int value;
    public int Value { get { return value; } }

    public void Update()
    {
        Interlocked.Add(ref value, 47); // UPDATE: use interlocked to not distract from the question being asked.
    }
}

我知道读它,写它时,我可以锁定:

I realise I could lock when reading it and writing it:

public int Value { get { lock(locker) return value; } }

public void Update()
{
    lock(locker)
    {
        value += 47;        
    }
}

和我都遵循使用锁始终是这种模式。不过我想减少我的code锁的数量(有很多,他们经常叫,我已经异形和 Montior.Enter()正在更多的时间,那么我想 - 因为它叫了这么多次)

And I have followed this pattern of using locks always. However I am trying to reduce the number of locks in my code (there are many and they are called frequently, I have profiled and Montior.Enter() is taking up more time then I would like - because it is called so many times).

更新:我不知道现在如果确实锁定将在确保我阅读的是最新的值有什么区别,它仍然可以从机器的CPU的缓存中不能它? (所有的锁保证是互斥的线程访问)。

UPDATE: I wonder now if that indeed the lock will make any difference in ensuring I am reading the most up to date value, it could still be from one of the machine's CPU caches couldn't it? (All the lock guarantees is mutual exclusive thread access).

我觉得挥发性将是答案,<一个href="http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(VOLATILE_CSHARPKEYWORD);k(TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV4.0%22);k(DevLang-CSHARP)&rd=true"相对=nofollow> MSDN 确实说:这确保了最先进的最新价值present在任何时候都在现场,但是我读的别处写那么当使用读取CPU指令仍然可以互换挥发性的这种情况下,我能得到的 myThreadSafe.Value A previous价值也许我可以忍受这一点 - 只有被淘汰一个更新

I thought volatile would be the answer, MSDN does say: "This ensures that the most up-to-date value is present in the field at all times", however I read elsewhere write then read CPU instructions can still be swapped when using volatile in which case I could get a previous value for myThreadSafe.Value perhaps I could live with that - only being out by one update.

什么是最有效的方式,我总是会得到的 myThreadSafe.Value

What is the most efficient way I will always get the most up-to-date value for myThreadSafe.Value?

更新:这code会被编译并运行在CPU体系结构:

UPDATE: This code will be compiled and run on CPU Architectures:

  • 86
  • 在AMD64(虽然我可以构建为86)
  • 的PowerPC
  • 在ARM(小端只)

使用运行时:

  • 在CLR 4.0版
  • 在单(我不知道单运行的版本,但如果它们对应的单声道版本:3.0,至少)。

我希望使用相同的code为所有构建!

I am hoping to use the same code for all builds!

推荐答案

好了,我相信我找到了答案,我关心的是平反!

OK, I believe I found the answer and my concern is vindicated!

在code恰好是线程安全的x86和AMD64因为他们无效时,该变量被写入导致之后的CPU的缓存中读取读取内存中的变量。引用Shafqay艾哈迈德报价杰弗里里希特:

The code happens to be thread-safe on x86 and AMD64 because they invalidate a CPUs cache when the variable is written to causing subsequent reads to read the variable from memory. to quote Shafqay Ahmed quoting Jeffrey Richter:

由于两个处理器可以有不同的高速缓存,这是柱塞的副本,它们可以有不同的值。在x86和x64处理器(根据杰弗里的著作)的目的是同步不同处理器的高速缓存,所以我们可能看不到的问题。

Since two processors can have different caches, which are copies of the ram, they can have different values. In x86 and x64 processors (according to Jeffrey’s book) are designed to sync the caches of different processors so we may not see the problem.

顺便用锁定互锁刷新从缓存中的变量,因此读取属性时,会一直用锁安全。从<一个href="http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three.aspx" rel="nofollow">http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three.aspx:

Incidentally using lock and Interlocked flushes the variable from cache, so using lock when reading the property would have been safe. From http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three.aspx:

锁保证存储器读取或修改内部锁被观察到是一致的,锁具保证只有一个线程访问的存储器的给定大块的时间,依此类推。

Locks guarantee that memory read or modified inside the lock is observed to be consistent, locks guarantee that only one thread accesses a given hunk of memory at a time, and so on.

当然,也不能保证在CLR规范读取由另一个线程更新的值时(不使用锁定同步构造)将是最最近给出。事实上,ARM的我很可能得到一个旧值使用线程安全的类,因为它是从 HTTP ://msdn.microsoft.com/en-us/magazine/jj553518.aspx

However there is no guarantee in the CLR specification given when reading a value updated by another thread (without using locking synchronization constructs) will be the most recent. Indeed on ARM I could well get an old value using ThreadSafe class as it is, from http://msdn.microsoft.com/en-us/magazine/jj553518.aspx:

如果您的code依赖于依赖于x86的CLR(而不是ECMA CLR规范)实施无锁算法,你要volatile关键字添加到相关的变量为宜。一旦你标记共享状态不稳定,CLR会照顾一切为您服务。如果你像大多数开发人员,你就可以运行在ARM上,因为你已经使用锁来保护共享数据,适当标记volatile变量和测试基于ARM的应用程序。

If your code relies on lock-free algorithms that depend on the implementation of the x86 CLR (rather than the ECMA CLR specification), you’ll want to add the volatile keyword to relevant variables as appropriate. Once you’ve marked shared state as volatile, the CLR will take care of everything for you. If you’re like most developers, you’re ready to run on ARM because you’ve already used locks to protect your shared data, properly marked volatile variables and tested your app on ARM.

如此看来,答案是读书的时候,我可以使用锁定或让我的字段挥发性,虽然也许我应该用锁,并尝试减少调用的数量,谁的工作编译器<一个男人href="http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three.aspx"相对=nofollow>说:

So it seems the answer is I can use a lock when reading or make my field volatile, though perhaps I should use lock and try reduce the number of calls, as a man who worked on the compiler says:

的情况,其中一个锁太慢的数量是非常小的,而且,你会得到code错误的,因为你不知道确切的内存模型的概率是非常大的。我不尝试写入任何低锁code除了互锁操作的最简单的用法。我离开了动荡的使用情况,真正的专家。

The number of situations in which a lock is too slow is very small, and the probability that you are going to get the code wrong because you don't understand the exact memory model is very large. I don't attempt to write any low-lock code except for the most trivial usages of Interlocked operations. I leave the usage of "volatile" to real experts.

这篇关于如何让阅读这种情况下原始的线程安全的无锁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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