java并发对象,Java中的并发对象创建

I'm reading a book "Java concurrency in practice" by Brian Goetz. Paragraphs 3.5 and 3.5.1 contains statements that I can not understand.

Consider the following code:

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);

}

}

Author states that:

In Java, Object constructor first writes default values to all fields before subclass constructor run.

Therefore it's possible to see field default value as a stale value.

Thread may see stale value the first time it reads a field and then a more up-to-date value the next time, which is why assertN  can throw AssertionError.

So, according to the text, with some unlucky timing it is possible that value = 0; and in the next moment value = 42.

I agree with point 1 that Object constructor firstly fills fields with default values. But I don't understand points 2 & 3.

Let's update authors code and consider the following example:

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");

}

}

I've added Thread.sleep(3000), to force thread to wait before object will be fully constructed.

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();

}

}

In example:

first thread inits holder object

second thread calls assertValue

Main Thread runs two threads:

new Thread(new Initialization()).start(); It tooks 3 seconds to fully construct Holder object

new Thread(new Checking()).start(); since Holder object still not constructed code will throw an NullPointerException

Therefore, it's impossible to emulate situation when field has default value.

My Questions:

Author was wrong about this concurrency problem?

Or It it impossible to emulate behaviour for fields default values?

解决方案

Did not reproduce it with your code. Here is an example to emulate un-safe publication. The strategy is let one thread publication Holder and let another check its value.

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();

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值