相关疑难解决方法(0)

Java内存模型:volatile变量和之前发生的

我想澄清一下,在关系与volatile变量一起工作之前会发生什么.我们有以下变量:

public static int i, iDst, vDst;
public static volatile int v;
Run Code Online (Sandbox Code Playgroud)

和线程A:

i = 1;
v = 2;
Run Code Online (Sandbox Code Playgroud)

和线程B:

vDst = v;
iDst = i;
Run Code Online (Sandbox Code Playgroud)

以下语句是否符合Java内存模型(JMM)?如果没有,那么正确的解释是什么?

  • i = 1总是发生在以前 v = 2
  • v = 2 发生 vDst = v在JMM 之前,只有它实际发生在时间之前
  • i = 1 发生 iDst = i在JMM 之前(并且iDst可以预测分配1)如果v = 2实际发生vDst = v在时间之前
  • 否则,在i = 1和之间的顺序iDst …

java volatile java-memory-model thread-synchronization happens-before

36
推荐指数
3
解决办法
2367
查看次数

JIT是否可以在某些表达式中将两个易失性读取合并为一个?

假设我们有一个volatile int a.一个线程呢

while (true) {
    a = 1;
    a = 0;
}
Run Code Online (Sandbox Code Playgroud)

而另一个线程呢

while (true) {
    System.out.println(a+a);
}
Run Code Online (Sandbox Code Playgroud)

现在,JIT编译器发出相应的汇编代码是不合法2*aa+a吗?

一方面,易失性读取的目的是它应该始终从内存中消失.

另一方面,两个读取之间没有同步点,所以我看不出a+a原子处理是非法的,在这种情况下我不会看到如何进行优化2*a会破坏规范.

我们将不胜感激参考JLS.

java jit volatile memory-model java-memory-model

28
推荐指数
2
解决办法
560
查看次数

Java重新排序会影响System.currentTimeMillis()吗?

根据Java Memory Model,只要执行结构良好,指令就可以重新排序.

所以我想知道,以下代码是否可能产生以下输出?

[代码] [在同一个主题中]

long a = System.currentTimeMillis();
long b = System.currentTimeMillis();
long c = System.currentTimeMillis();
Run Code Online (Sandbox Code Playgroud)

[输出]

a == 10, b == 20, c == 15
Run Code Online (Sandbox Code Playgroud)

如果不可能,那么JVM /实现会做些什么来防止这种情况发生?

java java-memory-model order-of-execution

18
推荐指数
1
解决办法
512
查看次数

发生在Java内存模型中的关系之前

关于JLS ch17 线程和锁,它说"如果一个动作发生在另一个之前,那么第一个动作在第二个之前可见并且在第二个之前被命令"; 我想知道:

(1)说"之前订购"的真正含义是什么?因为即使action_a发生在action_b之前,action_a也可以在action_b之后的某些实现中执行,对吧?

(2)如果action_a发生在action_b之前,是否意味着action_a绝不能看到action_b?或者action_a可能会看到或看不到action_b?

(3)如果action_a没有发生 - 在action_b之前,而action_b没有发生 - 在action_a之前,是否意味着action_a可能会看到或看不到action_b?

(4)之前没有任何循环发生,对吧?

任何答案将不胜感激:)

java jvm jvm-hotspot java-memory-model happens-before

6
推荐指数
2
解决办法
616
查看次数

Java,会不稳定也能保证可见性?

public class Stuff {
  private final Timer timer = new Timer(true);
  public static final int DEFAULT_TIMEOUT = 1500;
  private volatile int timeout = DEFAULT_TIMEOUT;


  public void doStuff(OtherStuff) {
     ...
     timer.schedule(timeout, ...);
  }

  public void setTimeout(int timeout) {
     this.timeout = timeout;
  }

  public int getTimeout() {
    return timeout;
  }

}
Run Code Online (Sandbox Code Playgroud)

除了可以从另一个类更改的超时变量外,只从1个线程访问此类的实例.在我的例子中是一个JMX bean,这意味着可以在运行时从管理界面改变超时.

doStuff()可以运行100次/秒,而setTimeout()可以每周运行一次 - 因此执行setTimeout()的人和执行doWork()的人之间的顺序并不重要.

timeout在这种情况下是否足够挥发?内存模型是否可以保证从一个线程设置此doStuff()方法对方法可见?

另一种似乎安全的替代方案就是:

public class Stuff {
  private final Timer timer = new Timer(true);
  public static final int DEFAULT_TIMEOUT = 1500;
  private int timeout …
Run Code Online (Sandbox Code Playgroud)

java concurrency

3
推荐指数
1
解决办法
909
查看次数