C# 互锁且易变

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1186515/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 10:19:12  来源:igfitidea点击:

Interlocked and volatile

c#.netmono

提问by trampster

I have a variable which I am using to represent state. It can be read and written to from multiple threads.

我有一个用来表示状态的变量。它可以从多个线程读取和写入。

I am using Interlocked.Exchangeand Interlocked.CompareExchangeto change it. However I am reading it from multiple threads.

我正在使用Interlocked.ExchangeInterlocked.CompareExchange更改它。但是,我正在从多个线程中读取它。

I know that volatilecan be used to make sure the variable is not cached locally but always reads directly from memory.

我知道这volatile可用于确保变量不在本地缓存,而是始终直接从内存中读取。

However if I set the variable to volatile then it generates a warning about using volatile and passing using ref to the Interlocked methods.

但是,如果我将变量设置为 volatile,那么它会生成关于使用 volatile 并将 using ref 传递给 Interlocked 方法的警告。

I want to ensure that each thread is reading the most recent value of the variable and not some cached version, but I can't use volatile.

我想确保每个线程都在读取变量的最新值,而不是某个缓存版本,但我不能使用 volatile。

There is a Interlocked.Readbut it is for 64 bit types and is not available on the compact framework. The documentation for it says that it is not needed for 32 bit types as they are already performed in a single operation.

有一个Interlocked.Read但它适用于 64 位类型,并且在紧凑型框架上不可用。它的文档说 32 位类型不需要它,因为它们已经在单个操作中执行了。

There are statements made across the internet that you don't need volatile if you are using the Interlocked methods for all your access. However you can't read a 32 bit variable using the Interlocked methods, so there is no way you can use Interlocked methods for all your access.

互联网上有一些声明,如果您使用 Interlocked 方法进行所有访问,则不需要 volatile。但是,您无法使用 Interlocked 方法读取 32 位变量,因此您无法使用 Interlocked 方法进行所有访问。

Is there some way to accomplish the thread safe read and write of my variable without using lock?

有什么方法可以在不使用锁的情况下完成我的变量的线程安全读写吗?

采纳答案by Anton Tykhyy

You can safely disregard that warning when you're using Interlocked.Xxxfunctions (see this question), because they always do volatile operations. So a volatilevariable is perfectly OK for shared state. If you want to get rid of the warning at all costs, you actually cando an interlocked read with Interlocked.CompareExchange (ref counter, 0, 0).

当您使用Interlocked.Xxx函数时,您可以放心地忽略该警告(请参阅此问题),因为它们总是执行易变的操作。所以一个volatile变量对于共享状态是完全可以的。如果你想不惜一切代价摆脱警告,你实际上可以Interlocked.CompareExchange (ref counter, 0, 0).

Edit:Actually, you need volatileon your state variable onlyif you are going to write to it directly (i.e. not using Interlocked.Xxx). As jerryjvl mentioned, reads of a variable updated with an interlocked (or volatile) operation will use the most recent value.

编辑:实际上,只有当您要直接写入(即不使用)时,需要volatile状态变量。正如 jerryjvl 所提到的,使用互锁(或易失性)操作更新的变量的读取将使用最新值。Interlocked.Xxx

回答by jerryjvl

Interlocked operations and volatile are not really supposed to be used at the same time. The reason you get a warning is because it (almost?) always indicates you have misunderstood what you are doing.

互锁操作和 volatile 不应该同时使用。您收到警告的原因是因为它(几乎?)总是表明您误解了自己在做什么。

Over-simplifying and paraphrasing:
volatileindicates that every read operation needs to re-read from memory because there might be other threads updating the variable. When applied to a field that can be read/written atomically by the architecture you are running on, this should be all you need to do unless you are using long/ulong, most other types can be read/written atomically.

过度简化和释义:
volatile表示每次读取操作都需要从内存中重新读取,因为可能有其他线程在更新变量。当应用于可以由您正在运行的体系结构以原子方式读取/写入的字段时,这应该是您需要做的全部,除非您使用 long/ulong,大多数其他类型都可以以原子方式读取/写入。

When a field is not marked volatile, you can use Interlockedoperations to make a similar guarantee, because it causes the cache to be flushed so that the update will be visible to all other processors... this has the benefit that you put the overhead on the update rather than the read.

当一个字段没有标记为 volatile 时,您可以使用Interlocked操作来做出类似的保证,因为它会导致缓存被刷新,以便所有其他处理器都可以看到更新......这样做的好处是您可以增加开销更新而不是读取。

Which of these two approaches performs best depends on what exactly you are doing. And this explanation is a gross over-simplification. But it should be clear from this that doing both at the same time is pointless.

这两种方法中哪一种效果最好取决于您究竟在做什么。这种解释是一种粗略的过度简化。但从这里应该可以清楚地看出,同时进行两者是没有意义的。