相关疑难解决方法(0)

发生在与Java中的易失性字段和同步块的关系之前 - 以及它们对非易失性变量的影响?

我对线程概念还很陌生,并尝试更多地了解它.最近,我发现了一篇关于Jeremy Manson撰写的" Java中易失手段"的博客文章,他写道:

当一个线程写入一个volatile变量,而另一个线程看到该写入时,第一个线程告诉第二个线程关于内存的所有内容,直到它执行对该volatile变量的写入.[...] 所有的由线程1看到的存储内容,才写信给[volatile] ready,必须是可见的主题2,它读取值后true进行ready.[自己强调]

现在,这是否意味着在写入volatile变量时,线程1的内存中保存的所有变量(volatile或not)将在读取volatile变量后变为可见?如果是这样,是否可以从官方Java文档/ Oracle源代码中将该语句拼凑起来?从哪个版本的Java开始这个工作?

特别是,如果所有线程共享以下类变量:

private String s = "running";
private volatile boolean b = false;
Run Code Online (Sandbox Code Playgroud)

并且线程1首先执行以下操作:

s = "done";
b = true;
Run Code Online (Sandbox Code Playgroud)

然后线程2执行(在线程1写入volatile字段之后):

boolean flag = b; //read from volatile
System.out.println(s);
Run Code Online (Sandbox Code Playgroud)

这会保证打印"完成"吗?

如果我将写入和读取放入块中而不是声明b,会发生什么?volatilesynchronized

另外,在题为" 线程之间是否共享静态变量? "的讨论中,@ TREE 写道:

不要使用volatile来保护多个共享状态.

为什么?(对不起;我还没有就其他问题发表评论,或者我会在那里问过......)

java multithreading volatile synchronized

49
推荐指数
3
解决办法
8383
查看次数

易失性保证和无序执行

重要编辑我知道在发生两个赋值的线程中 "发生在之前" 我的问题是,另一个线程是否可能读取"b"非空,而"a"仍为空.所以我知道如果你从与之前调用setBothNonNull(...)的线程相同的线程调用doIt(),那么它就不能抛出NullPointerException.但是如果一个人从另一个线程调用doIt()不是调用setBothNonNull(...)的那个呢?

请注意,这个问题仅仅是对volatile关键字和volatile保证:这是不是synchronized关键字(所以请不要回答"您必须使用同步"因为我没有任何问题要解决:我只是想了解volatile担保关于无序执行(或缺乏保证).

假设我们有一个包含两个volatileString引用的对象,它们被构造函数初始化为null,并且我们只有一种方法来修改两个String:通过调用setBoth(...)并且我们之后只能将它们的引用设置为非null引用(只允许构造函数将它们设置为null).

例如(这只是一个例子,毫无疑问):

public class SO {

    private volatile String a;
    private volatile String b;

    public SO() {
        a = null;
        b = null;
    }

    public void setBothNonNull( @NotNull final String one, @NotNull final String two ) {
        a = one;
        b = two;
    }

    public String getA() …
Run Code Online (Sandbox Code Playgroud)

java volatile java-memory-model

41
推荐指数
2
解决办法
9239
查看次数

关于可见性及时性的易失性的详细语义

考虑一下volatile int sharedVar.我们知道JLS为我们提供了以下保证:

  1. 写入线程的每个动作在w其写入值之前isharedVar程序顺序happens-before写入动作;
  2. 的值写入i通过w happens-before的成功读取isharedVar由读取线程r;
  3. 成功读取isharedVar由读线程r happens-before的所有后续行动r的程序顺序.

然而,仍有给出没有挂钟时间的保证,当读线程将观察值i.一个完全不会让读取线程看到该值的实现仍然符合此契约.

我已经考虑了一段时间,我看不到任何漏洞,但我认为必须有.请指出我的推理漏洞.

java volatile java-memory-model

21
推荐指数
1
解决办法
1086
查看次数

挥发性变量和订购前发生的事情

我有两个主题:

主题:1

a = 1;
x = b;
Run Code Online (Sandbox Code Playgroud)

主题:2

b = 1
y = a
Run Code Online (Sandbox Code Playgroud)

这里a和b被声明为volatile.我不明白在a = 1之间如何创建"before-before"边缘; 和y = a; 在x = b之间; 和b = 1;

我知道通过使用volatile变量可以防止从线程缓存中读取过时值.但是,在订购之前,如何确保变量发生变化.

具体来说,我不明白这一点:

对每个后续读取相同字段之前发生对易失性字段的写入.

锄头有用吗?

java volatile

12
推荐指数
2
解决办法
5072
查看次数

发生在 volatile 之前和重新排序

有多个代码示例假定以下指令(1)(2)不能重新排序:

int value;
volatile boolean ready;

// ...

value = 1;     // (1)
ready = true;  // (2)
Run Code Online (Sandbox Code Playgroud)

后一个 Stack Overflow 答案是指 JLS §17.4.5

如果 x 和 y 是同一线程的动作,并且 x 在程序顺序中排在 y 之前,则 hb(x, y)。

但是我不明白为什么这应该适用于这里,因为 JLS示例 17.4-1还指出:

[...] 允许编译器重新排序任一线程中的指令,前提是这不会影响该线程的单独执行。

这显然是这里的情况。

JLS 中特定于的所有其他定义volatile仅针对相同的 volatile 变量,而不针对其他操作:

对 volatile 字段(第 8.3.1.4 节)的写入发生在该字段的每次后续读取之前。


在人们看到 volatile (读或写)的使用可能不会重新排序的保证时,我感到困惑。

您能否将您的解释基于 JLS 或基于 JLS 的其他来源。

java multithreading java-memory-model jls

6
推荐指数
1
解决办法
220
查看次数

用volatile更新和交换HashMap

背景

我有一个大的数据映射(HashMap),保存在内存中,并由后台线程进行增量更新(基于传入消息):

<KEY> => <VALUE>
...
Run Code Online (Sandbox Code Playgroud)

最终用户将通过REST API查询它:

GET /lookup?key=<KEY>
Run Code Online (Sandbox Code Playgroud)

一旦收到特殊控制消息,即不会立即应用更新,而是分批进行更新,即

MESSAGE: "Add A" 

A=<VALUE>   //Not visible yet

MESSAGE: "Add B"

B=<VALUE>   //Not visible yet

MESSAGE: "Commit"

//Updates are now visible to the end-users
A=<VALUE>
B=<VALUE
Run Code Online (Sandbox Code Playgroud)

我设计的架构如下:

<KEY> => <VALUE>
...
Run Code Online (Sandbox Code Playgroud)

问题

将write-> read写入volatile字段会在边缘之前发生:

在随后每次对该字段进行读取之前,都会写入一个易失字段(第8.3.1.4节)。

https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5

并且正确选择了宽限期,我希望在交换之后,最终用户请求(一次全部)将看到对任何应用到PassiveCopy(通过putAll())的更新。

确实是这样,还是有什么极端情况会使这种方法失败?

注意

我知道创建Map的副本(以便每次都将一个新的Map实例分配给activeCopy)是安全的,但是我不想这样做(因为它确实很大)。

java volatile

5
推荐指数
1
解决办法
104
查看次数