Mat*_*ski 8 java concurrency multithreading java-memory-model
我想编写一个简单的线程安全类,可用于设置或获取Integer值.
最简单的方法是使用synchronized关键字:
public class MyIntegerHolder {
private Integer value;
synchronized public Integer getValue() {
return value;
}
synchronized public void setValue(Integer value) {
this.value = value;
}
}
Run Code Online (Sandbox Code Playgroud)
我也可以尝试使用volatile:
public class MyIntegerHolder {
private volatile Integer value;
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
}
Run Code Online (Sandbox Code Playgroud)
具有volatile关键字的类是否是线程安全的?
考虑以下事件序列:
它遵循Java语言规范
但我不知道它是如何遵循规范"1" 发生 - 在 "2" 之前所以我怀疑"1" 不会 发生 - 在 "2" 之前.
我怀疑线程C可能读取7或5.我认为具有volatile关键字的类不是线程安全的,并且以下序列也是可能的:
假设具有volatile的 MyIntegerHolder 不是线程安全的,我是否正确?
是否可以使用AtomicInteger创建一个线程安全的整数持有者:
public class MyIntegerHolder {
private AtomicInteger atomicInteger = new AtomicInteger();
public Integer getValue() {
return atomicInteger.get();
}
public void setValue(Integer value) {
atomicInteger.set(value);
}
}
Run Code Online (Sandbox Code Playgroud)
?
这是Java Concurrency In Practice一书的一个片段:
" 原子变量的读写与volatile变量具有相同的内存语义. "
编写线程安全的 MyIntegerHolder 的最佳(最好是非阻塞)方法是什么?
如果你知道答案,我想知道为什么你认为它是正确的.它符合规范吗?如果是这样,怎么样?
Mat*_*ski -1
这个问题对我来说并不容易,因为我认为(错误地)了解有关happens -before关系的所有内容可以使人完全理解Java内存模型以及易失性的语义。
我在这个文档中找到了最好的解释: “JSR-133:JavaTM内存模型和线程规范”
上述文档中最相关的片段是“7.3 Well-Formed Executions”部分。
Java 内存模型保证程序的所有执行都是格式正确的。仅当满足以下条件时,执行才是格式良好的:
Happens-before 一致性通常足以得出有关程序行为的结论 - 但在这种情况下不行,因为易失性写入不会发生在另一个易失性写入之前。
带有volatile 的MyIntegerHolder是线程安全的,但它的安全性来自于同步顺序的一致性。
在我看来,当线程 B 即将将该值设置为 7 时,A 不会通知 B 在那一刻之前它所做的所有事情(正如其他答案之一所建议的那样) - 它只通知 B 有关 volatile 变量的值。如果线程 B 执行的操作是读取而不是写入,则线程 A 会向 B 通知所有信息(为其他变量赋值)(在这种情况下,这两个线程执行的操作之间将存在发生前关系)。
| 归档时间: |
|
| 查看次数: |
4011 次 |
| 最近记录: |