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

问题描述

在oracle Java文档,以下说明:

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

它还说:


  • 读取和写入对于参考变量和大多数都是原子的
    原始变量(除了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提供了一个更严格的一致性模型,它禁止这个相对性问题,这被称为。您可以在和。最重要的部分是:

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:

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

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

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

10-22 08:59