易失性关键字和内存一致性错误 [英] The volatile key word and memory consistency errors

查看:138
本文介绍了易失性关键字和内存一致性错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在oracle Java文档位于此处,以下说明:

In the oracle Java documentation located here, the following is said:


原子操作不能交错,因此可以使用它们而不用担心线程干扰。但是,这并不能消除同步原子操作的所有需要​​,因为仍然可能存在内存一致性错误。使用volatile变量可以降低内存一致性错误的风险,因为对volatile变量的任何写入都会建立与之后读取同一变量的先发生关系。这意味着对volatile变量的更改始终对其他线程可见。更重要的是,它还意味着当一个线程读取一个volatile变量时,它不仅会看到volatile的最新变化,还会看到导致变化的代码的副作用。

Atomic actions cannot be interleaved, so they can be used without fear of thread interference. However, this does not eliminate all need to synchronize atomic actions, because memory consistency errors are still possible. Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change.

它还说:


  • 读取和写入对于参考变量和大多数都是原子的
    原始变量(除了long和double之外的所有类型)。

  • 读取和写入对于所有声明为volatile的变量都是原子的(包括long
    和double变量)。

我对这些陈述有两个问题:


  1. 使用volatile变量可降低内存一致性错误的风险 - 它们的意思是降低风险,以及如何使用volatile时仍然可以记忆一致性错误吗?

  1. "Using volatile variables reduces the risk of memory consistency errors" - What do they mean by "reduces the risk", and how is a memory consistency error still possible when using volatile?

将volatile放在非双非长基元上的唯一效果是真的吗?是为了启用发生-b之前与其他线程后续读取的关系?我问这个,因为看起来这些变量已经有原子读数。

Would it be true to say that the only effect of placing volatile on a non-double, non-long primitive is to enable the "happens-before" relationship with subsequent reads from other threads? I ask this since it seems that those variables already have atomic reads.


推荐答案

降低风险是什么意思?

Atomicity Java内存模型。但是,比 Atomicity 更重要的是以下问题:

Atomicity is one issue addressed by the Java Memory Model. However, more important than Atomicity are the following issues:


  • 内存架构,例如: CPU缓存对读写操作的影响

  • CPU优化,例如:加载和存储的重新排序

  • 编译器优化,例如添加和删​​除装载和存储

以下列表包含一个经常使用的示例。 x y 上的操作是原子的。不过,该程序可以打印两行。

The following listing contains a frequently used example. The operations on x and y are atomic. Still, the program can print both lines.

int x = 0, y = 0;

// thread 1
x = 1
if (y == 0) System.out.println("foo");

// thread 2
y = 1
if (x == 0) System.out.println("bar");

但是,如果你声明 x y as volatile ,只能打印两行中的一行。

However, if you declare x and y as volatile, only one of the two lines can be printed.

使用volatile时如何仍然存在内存一致性错误?

以下示例使用 volatile 。但是,更新可能仍会丢失。

The following example uses volatile. However, updates might still get lost.

int x = 0;

// thread 1
x += 1;

// thread 2
x += 1;






说出来是真的吗将volatile放在非双非长基元上的唯一效果是启用之前发生关系以及其他线程的后续读取吗?

发生前 - 经常被误解。 定义的一致性模型发生在之前很弱并且难以正确使用。这可以通过以下示例进行演示,该示例称为独立写入的独立读取(IRIW):

Happens-before is often misunderstood. The consistency model defined by happens-before is weak and difficult to use correctly. This can be demonstrated with the following example, that is known as Independent Reads of Independent Writes (IRIW):

volatile int x = 0, y = 0;

// thread 1
x = 1;

// thread 2
y = 1;

// thread 3
if (x == 1) System.out.println(y);

// thread 4
if (y == 1) System.out.println(x);

只有发生在之前,两个 0 s将是有效的结果。然而,这显然是违反直觉的。出于这个原因,Java提供了一个更严格的一致性模型,它禁止这个相对性问题,这被称为顺序一致性。您可以在§部分找到它17.4.3 Java语言规范的§17.4.5。最重要的部分是:

Only with happens-before, two 0s would be valid result. However, that's apparently counter-intuitive. For that reason, Java provides a stricter consistency model, that forbids this relativity issue, and that is known as sequential consistency. You can find it in sections §17.4.3 and §17.4.5 of the Java Language Specification. The most important part is:


当且仅当所有顺序一致的执行都是免费的时,程序正确同步数据竞赛。如果程序正确同步,则程序的所有执行都将按顺序一致(第17.4.3节)。

A program is correctly synchronized if and only if all sequentially consistent executions are free of data races. If a program is correctly synchronized, then all executions of the program will appear to be sequentially consistent (§17.4.3).

意味着, volatile 为您提供超过之前发生的。如果用于所有冲突访问,它会为您提供顺序一致性§17.4.3

That means, volatile gives you more than happens-before. It gives you sequential consistency if used for all conflicting accesses (§17.4.3).

这篇关于易失性关键字和内存一致性错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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