gpt4 book ai didi

java - Java volatile 变量在读取之前是否强加了先行关系?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:50:47 26 4
gpt4 key购买 nike

我有一段代码是这样的:

片段A:

class Creature {
private static long numCreated;
public Creature() {
synchronized (Creature.class) {
numCreated++;
}
}
public static long numCreated() {
return numCreated;
}
}

根据我的理解,由于numCreated的读取不是同步的,如果Thread-A在下午1点创建了一个Creature,而Thread-B读取了numCreated() 在下午 2 点,numCreated() 很可能返回 0 或 1(即使 Thread-A 在下午 1.05 完成了对象的初始化)。

所以我在 numCreated() 中添加了 synchronized:

片段 B:

class Creature {
private static long numCreated;
public Creature() {
synchronized (Creature.class) {
numCreated++;
}
}
public static synchronized long numCreated() { // add "synchronized"
return numCreated;
}
}

一切都很好,除了我在想,如果我将它修改为 Snippet C,变量 numCreated 是否仍然正确同步?

片段 C:

class Creature {
private static volatile long numCreated; // add "volatile"
public Creature() {
synchronized (Creature.class) {
numCreated++;
}
}
public static long numCreated() { // remove "synchronized"
return numCreated;
}
}

对于 Snippet C,是否可以保证只要 Thread-A 在下午 1:05 完成对象创建,Thread-B 对 numCreated() 的调用肯定会返回 1 ?

PS:我知道在实际情况下我可能会使用 AtomicLong 但这是出于学习目的

最佳答案

参见 http://download.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility :

A write to a volatile field happens-before every subsequent read of that same field. Writes and reads of volatile fields have similar memory consistency effects as entering and exiting monitors, but do not entail mutual exclusion locking.

所以答案是肯定的。在构造函数中写入 volatile 发生在 numCreated() 中读取 volatile 之前。并且由于非原子增量仍然在同步块(synchronized block)中完成,所以同步是可以的(增量不是原子的,但是 volatile long 的写入是)。

关于java - Java volatile 变量在读取之前是否强加了先行关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8023721/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com