No *_* QA 11 java concurrency multithreading object safe-publication
我正在读Brian Goetz的一本书"实践中的Java并发".第3.5和3.5.1段包含我无法理解的陈述.
请考虑以下代码:
public class Holder {
private int value;
public Holder(int value) {
this.value = value;
}
public void assertValue() {
if (value != value) throw new AssertionError("Magic");
}
}
class HolderContainer {
// Unsafe publication
public Holder holder;
public void init() {
holder = new Holder(42);
}
}
Run Code Online (Sandbox Code Playgroud)
作者说:
因此,根据文本,有些不幸的时机可能值= 0; 在下一刻,值= 42.
我同意第1点,Object构造函数首先使用默认值填充字段.但我不明白第2和第3点.
让我们更新作者代码并考虑以下示例:
public class Holder {
int value;
public Holder(int value) {
//Sleep to prevent constructor to finish too early
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.value = value;
}
public void assertValue() {
if(value != value) System.out.println("Magic");
}
}
Run Code Online (Sandbox Code Playgroud)
我添加了Thread.sleep(3000),强制线程在完全构造对象之前等待.
public class Tests {
private HolderContainer hc = new HolderContainer();
class Initialization implements Runnable {
public void run() {
hc.init();
}
}
class Checking implements Runnable {
public void run() {
hc.holder.assertValue();
}
}
public void run() {
new Thread(new Initialization()).start();
new Thread(new Checking()).start();
}
}
Run Code Online (Sandbox Code Playgroud)
例如:
主线程运行两个线程:
因此,当字段具有默认值时,不可能模拟情况.
我的问题:
没有用您的代码重现它。这是一个模拟不安全发布的示例。该策略是让一个线程发布Holder并让另一个线程检查其值。
class Holder {
private volatile int value;
public Holder(int value, HolderContainer container) {
container.holder = this; // publication this object when it is not initilized properly
try {
Thread.sleep(10);
} catch (Exception e) {
}
this.value = value; // set value
}
public int getValue() {
return value;
}
}
class HolderContainer {
public Holder holder;
public Holder getHolder() {
if (holder == null) {
holder = new Holder(42, this);
}
return holder;
}
}
public class Tests {
public static void main(String[] args) {
for (int loop = 0; loop < 1000; loop++) {
HolderContainer holderContainer = new HolderContainer();
new Thread(() -> holderContainer.getHolder()).start();
new Thread(() -> {
Holder holder = holderContainer.getHolder();
int value1 = holder.getValue(); // might get default value
try {
Thread.sleep(10);
} catch (Exception e) {
}
int value2 = holder.getValue(); // might get custom value
if (value1 != value2) {
System.out.println(value1 + "--->" + value2);
}
}).start();
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
195 次 |
| 最近记录: |