JCIP предупреждает нас о неправильно опубликованных объектах (см. здесь ).Если объект является изменяемым, JVM может решить опубликовать объект до завершения его инициализации.
Таким образом, код
class Holder {public int h = 0;public Holder(int _h) {h = _h;}}
a = new Holder(10);
может стать эффективным
a = new Holder();
// inlined constructor
a.h = 10;
затем, когда другой поток обращается к a.h
, предполагая, что он никогда не может быть 0, он может завершиться ошибкой
// Thread #1 executing
a = new Holder();
// Thread #2 preempts
if (a != null) System.out.println("result: "+(100/a.h)); // oops...
Я пытался продемонстрировать эту проблему.Но ни один код, который я написал, не продемонстрировал этого.То, что я сделал, было:
static class Holder {
int h = 0;
int dummy = 0;
public Holder(int h) {
// if construction takes time, maybe I have better chance creating the bug...
for (long i=0;i<1000*1000;i++) {
dummy += i*(-1+(i%2*2));
}
this.h = h;
}
public int verifyNonZero() {
return 1/h;
}
}
Затем я запустил 1000 потоков, публикующих new Holder()
в статическую переменную holder
, и другие 1000 потоков, работающих holder.verifyNonZero()
.См. полный текст .
Это не очень помогло с Java 1.6, даже с -server
.