getValue() 中需要同步吗?需要挥发性吗?
is synchronized needed in getValue() ? & volatile needed?
我有一个 class 多线程应用程序:
public class A {
private volatile int value = 0; // is volatile needed here?
synchronized public void increment() {
value++; // Atomic is better, agree
}
public int getValue() { // synchronized needed ?
return value;
}
}
关键字 volatile
为您提供可见性方面,否则您可能会读取一些陈旧的值。易失性读取添加了一个内存屏障,这样编译器、硬件或 JVM 就无法以违反内存模型提供的可见性保证的方式重新排序内存操作。根据内存模型,对易失性字段的写入 发生在 每次后续读取同一字段之前,因此您可以保证读取最新值。
还需要关键字 synchronized
,因为您正在执行必须自动完成的复合操作 value++
。您读取该值,在 CPU 中递增它,然后将其写回。所有这些动作都必须以原子方式完成。但是,您不需要 synchronize
读取路径,因为关键字 volatile
保证了可见性。事实上,在读取路径上同时使用 volatile
和 synchronize
会造成混淆,并且不会提供任何性能或安全优势。
通常鼓励使用原子变量,因为它们使用内置于 CPU 中的 CAS 指令使用非阻塞同步,从而产生低锁争用和更高的吞吐量。如果用原子变量写的话,就是这样了。
public class A {
private final LongAdder value = new LongAdder();
public void increment() {
value.add(1);
}
public int getValue() {
return value.intValue();
}
}
我有一个 class 多线程应用程序:
public class A {
private volatile int value = 0; // is volatile needed here?
synchronized public void increment() {
value++; // Atomic is better, agree
}
public int getValue() { // synchronized needed ?
return value;
}
}
关键字 volatile
为您提供可见性方面,否则您可能会读取一些陈旧的值。易失性读取添加了一个内存屏障,这样编译器、硬件或 JVM 就无法以违反内存模型提供的可见性保证的方式重新排序内存操作。根据内存模型,对易失性字段的写入 发生在 每次后续读取同一字段之前,因此您可以保证读取最新值。
还需要关键字 synchronized
,因为您正在执行必须自动完成的复合操作 value++
。您读取该值,在 CPU 中递增它,然后将其写回。所有这些动作都必须以原子方式完成。但是,您不需要 synchronize
读取路径,因为关键字 volatile
保证了可见性。事实上,在读取路径上同时使用 volatile
和 synchronize
会造成混淆,并且不会提供任何性能或安全优势。
通常鼓励使用原子变量,因为它们使用内置于 CPU 中的 CAS 指令使用非阻塞同步,从而产生低锁争用和更高的吞吐量。如果用原子变量写的话,就是这样了。
public class A {
private final LongAdder value = new LongAdder();
public void increment() {
value.add(1);
}
public int getValue() {
return value.intValue();
}
}