【发布时间】:2018-06-23 03:29:27
【问题描述】:
这是原始代码
//@author Brian Goetz and Tim Peierls
@ThreadSafe
public class SafePoint {
@GuardedBy("this") private int x, y;
private SafePoint(int[] a) {
this(a[0], a[1]);
}
public SafePoint(SafePoint p) {
this(p.get());
}
public SafePoint(int x, int y) {
this.set(x, y);
}
public synchronized int[] get() {
return new int[]{x, y};
}
public synchronized void set(int x, int y) {
this.x = x;
this.y = y;
}
}
这里很好,私有 int x,y 不是最终的,因为构造函数中的 set 方法在调用 get 时会导致发生在关系之前,因为它们使用相同的锁。
现在这里是修改后的版本和一个 main 方法,我希望在运行一段时间后抛出一个 AssertionError,因为我删除了 set 方法中的 synchronized 关键字。我将构造函数设为私有,以便成为唯一调用它的人,以防有人指出它因此不是线程安全的,这不是我问题的重点。
无论如何,我现在已经等了很久,没有抛出任何 AssertionErrors。现在我厌倦了这个修改后的类在某种程度上是线程安全的,即使根据我所学到的,这并不是因为 x 和 y 不是最终的。有人能告诉我为什么 AssertionError 仍然没有被抛出吗?
public class SafePointProblem {
static SafePoint sp = new SafePoint(1, 1);
public static void main(String[] args) {
new Thread(() -> {
while (true) {
final int finalI = new Random().nextInt(50);
new Thread(() -> {
sp = new SafePoint(finalI, finalI);
}).start();
}
}).start();
while (true) {
new Thread(() -> {
sp.assertSanity();
int[] xy = sp.get();
if (xy[0] != xy[1]) {
throw new AssertionError("This statement is false 1.");
}
}).start();
}
}
}
class SafePoint {
private int x, y;
public SafePoint(int x, int y) {
this.set(x, y);
}
public synchronized int[] get() {
return new int[]{x, y};
}
// I removed the synchronized from here
private void set(int x, int y) {
this.x = x;
this.y = y;
}
public void assertSanity() {
if (x != y) {
throw new AssertionError("This statement is false2.");
}
}
}
【问题讨论】:
标签: java multithreading concurrency visibility jit