具有释放/获取语义的易失性

发布于 2024-11-17 19:00:03 字数 518 浏览 2 评论 0原文

从 Java 5 开始,易失性 关键字具有释放/获取语义,以使副作用对其他线程可见(包括对非易失性变量的赋值!)。以这两个变量为例:

int i;
volatile int v;

请注意,i 是一个常规的非易失性变量。假设线程 1 执行以下语句:

i = 42;
v = 0;

在稍后的某个时间点,线程 2 执行以下语句:

int some_local_variable = v;
print(i);

根据 Java 内存模型,线程 1 中写入 v 后读取v 确保线程 2 看到线程 1 中执行的对 i 的写入,因此打印值 42。

我的问题是:在 C# 中,易失性 是否具有相同的释放/获取语义?

Since Java 5, the volatile keyword has release/acquire semantics to make side-effects visible to other threads (including assignments to non-volatile variables!). Take these two variables, for example:

int i;
volatile int v;

Note that i is a regular, non-volatile variable. Imagine thread 1 executing the following statements:

i = 42;
v = 0;

At some later point in time, thread 2 executes the following statements:

int some_local_variable = v;
print(i);

According to the Java memory model, the write of v in thread 1 followed by the read of v in thread 2 ensures that thread 2 sees the write to i executed in thread 1, so the value 42 is printed.

My question is: does volatile have the same release/acquire semantics in C#?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

感情旳空白 2024-11-24 19:00:03

C# 中“易失性”的语义在 C# 6.0 规范。我鼓励您在规范中查找它,而不是在这里重现它们,然后确定使用“易失性”太复杂和危险,然后返回使用锁。这就是我一直做的事情。

请参阅“ 7.10 执行顺序”和“14.5.4 易失性字段< /a>”在 C# 6.0 规范中。


C# 5.0 规范中,请参阅“3.10 执行顺序”和“10.5.3 易失性字段”

The semantics of "volatile" in C# are defined in sections 7.10 and 14.5.4 of the C# 6.0 specification. Rather than reproduce them here, I encourage you to look it up in the spec, and then decide that it is too complicated and dangerous to use "volatile", and go back to using locks. That's what I always do.

See "7.10 Execution order" and "14.5.4 Volatile fields" in the C# 6.0 specification.


In the C# 5.0 specification, see "3.10 Execution Order" and "10.5.3 Volatile Fields"

郁金香雨 2024-11-24 19:00:03

好吧,我相信它可以确保 if some_local_variable 被读取为 0 (由于写入 v), i 将被读取为 42。

棘手的部分是“在稍后的某个时间点”。虽然波动性通常是通过“刷新”写入来讨论的,但这并不是规范中实际定义的方式(Java 或 C#)。

来自 C# 4 语言规范,第 10.5.3 节:

对于非易失性字段,重新排序指令的优化技术可能会在多线程程序中导致意外和不可预测的结果,这些程序在没有同步的情况下访问字段,例如由锁定语句提供的同步(第 8.12 节)。这些优化可以由编译器、运行时系统或硬件来执行。对于易失性字段,此类重新排序优化受到限制:

  • 对易失性字段的读取称为易失性读取。易失性读取具有“获取语义”;也就是说,它保证发生在指令序列中发生在它之后的任何内存引用之前。
  • 对易失性字段的写入称为易失性写入。易失性写入具有“释放语义”;也就是说,它保证发生在指令序列中写入指令之前的任何内存引用之后。

然后有一个与您的示例非常相似的示例,但条件是从 volatile 变量读取的值。

和 Eric 一样,我自己也强烈避免依赖 volatility。这很难推理,最好留给世界上的乔·达菲/斯蒂芬·图布斯。

Well, I believe it ensures that if some_local_variable is read as 0 (due to the write to v), i will be read as 42.

The tricky part is "at some later point in time". While commonly volatility is talked about in terms of "flushing" writes, that's not how it's actually defined in the spec (either Java or C#).

From the C# 4 language spec, section 10.5.3:

For non-volatile fields, optimization techniques that reorder instructions can lead to unexpected and unpredictable results in multi-threaded programs that access fields without synchronization such as that provided by the lock-statement (§8.12). These optimizations can be performed by the compiler, by the run-time system, or by hardware. For volatile fields, such reordering optimizations are restricted:

  • A read of a volatile field is called a volatile read. A volatile read has “acquire semantics”; that is, it is guaranteed to occur prior to any references to memory that occur after it in the instruction sequence.
  • A write of a volatile field is called a volatile write. A volatile write has “release semantics”; that is, it is guaranteed to happen after any memory references prior to the write instruction in the instruction sequence.

There's then an example which is quite similar to yours, but conditional on the value read from the volatile variable.

And like Eric, I'd strongly avoid relying on volatile myself. It's hard to reason about, and best left to the Joe Duffy/Stephen Toubs of the world.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文