今天我实验室的敏感操作完全错了.电子显微镜上的执行器越过它的边界,在一系列事件之后,我损失了1200万美元的设备.我已将故障模块中的40K以上线路缩小到:
import java.util.*;
class A {
static Point currentPos = new Point(1,2);
static class Point {
int x;
int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void main(String[] args) {
new Thread() {
void f(Point p) {
synchronized(this) {}
if (p.x+1 != p.y) {
System.out.println(p.x+" "+p.y);
System.exit(1);
}
}
@Override
public void run() {
while (currentPos == null);
while (true)
f(currentPos);
}
}.start();
while (true)
currentPos = new Point(currentPos.x+1, currentPos.y+1);
} …Run Code Online (Sandbox Code Playgroud) 根据Java语言规范,构造函数不能被标记为同步,因为在创建它的线程完成之前,其他线程无法看到正在创建的对象.这看起来有点奇怪,因为在构造对象时我确实可以有另一个线程查看对象:
public class Test {
public Test() {
final Test me = this;
new Thread() {
@Override
public void run() {
// ... Reference 'me,' the object being constructed
}
}.start();
}
}
Run Code Online (Sandbox Code Playgroud)
我知道这是一个非常人为的例子,但理论上似乎有人可以提出一个更现实的案例,标记构造函数同步将是合法的,以防止像这样的线程的比赛.
我的问题是:Java有没有理由不在构造函数上禁用synchronized修饰符?也许我上面的例子是有缺陷的,或者也许没有理由,这是一个任意的设计决定.在任何一种情况下,我都很好奇,很想知道答案.
我正在读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 { …Run Code Online (Sandbox Code Playgroud) 让我们看看这个简单的Java程序:
import java.util.*;
class A {
static B b;
static class B {
int x;
B(int x) {
this.x = x;
}
}
public static void main(String[] args) {
new Thread() {
void f(B q) {
int x = q.x;
if (x != 1) {
System.out.println(x);
System.exit(1);
}
}
@Override
public void run() {
while (b == null);
while (true) f(b);
}
}.start();
for (int x = 0;;x++)
b = new B(Math.max(x%2,1));
}
}
Run Code Online (Sandbox Code Playgroud)
主线程
主线程创建的实例B与x设置为1,则该实例写入静态字段 …