如何在实践中理解java并发性这本书的一个例子?
清单3.15。如果未正确发布,则有失败风险的类别 我的第一个问题是,如果(n!=n),为什么javac不优化如何在实践中理解java并发性这本书的一个例子?,java,concurrency,assertions,java-threads,Java,Concurrency,Assertions,Java Threads,清单3.15。如果未正确发布,则有失败风险的类别 我的第一个问题是,如果(n!=n),为什么javac不优化 下面是我的示例演示 public class TestSync { private int n; public TestSync(int n) { this.n = n; } public void assertSanity() { if(n!=n) throw new AssertionErro
下面是我的示例演示
public class TestSync {
private int n;
public TestSync(int n) {
this.n = n;
}
public void assertSanity() {
if(n!=n)
throw new AssertionError("This statement is false");
}
private static TestSync test;
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
if(test == null) test = new TestSync(2);
else test = null;
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
if(test != null)
try {
test.assertSanity();
} catch (NullPointerException e) {
}
}
}
}).start();
}
}
我的第二个问题是我做的对吗?因为在我运行演示时没有发生异常
更新
1.除了我的第一个问题外:
javap-ctestsync.class
public void assertSanity();
Code:
0: aload_0
1: getfield #3 // Field n:I
4: aload_0
5: getfield #3 // Field n:I
8: if_icmpeq 21
11: new #4 // class java/lang/AssertionError
14: dup
15: ldc #5 // String This statement is false
17: invokespecial #6 // Method java/lang/AssertionError."<init>":(Ljava/lang/Object;)V
20: athrow
21: return
public void assertSanity();
代码:
0:aload_0
1:getfield#3//字段n:I
4:aload_0
5:getfield#3//字段n:I
8:if_icmpeq 21
11:new#4//class java/lang/AssertionError
14:dup
15:ldc#5//String这句话是假的
17:invokespecial#6//方法java/lang/AssertionError.“:(Ljava/lang/Object;)V
20:athrow
21:返回
我认为javac会将if(n!=n)
优化为if(false)
,并将其缩小
2.为什么我仍然在if(test!=null)
之后添加try{}catch(NullPointerException e)
因为我认为字段test
可能由之后的另一个线程设置null
,如果(test!=null)
首先,javac
几乎从不优化代码,您正在编译。只有当值是编译时常量时,才需要javac
在编译时对表达式求值,而表达式本身就是编译时常量,请参阅
然而,操作在运行时会得到优化,即使没有线程同步措施,优化器也可以使用乐观的假设,比如变量在两次读取之间不会改变。所以n=n
表达式一开始计算为true
的可能性很低,因为两次读取之间的时间很短,并且在优化器启动后几乎永远不会为true
。所以当表达式n=n
不能保证总是假
,在实践中不太可能遇到真
当然,根据墨菲定律,不管怎样,当你试图挑起错误时,它永远不会发生,但偶尔会发生在客户身上,但永远不会重现
⑨注意,即使第二个线程由于争用条件读取初始值0
,n=n
如果在随后的读取中不再次读取首字母0
,则只会失败。问题是什么?你怎么知道javac没有优化它?为什么在空对象的if语句中有一个NullPointerException的try-catch?@cricket\u 007已经更新了我的问题我可能是错的,但是test
应该是synchronized
?@cricket\u 007是的,但是我想让示例按照假设的那样抛出AssertionError异常到n=n表达式以一个很低的可能性开始,我认为false
应该是true
你是对的。n=n
非常不自然,很容易混淆。
public void assertSanity();
Code:
0: aload_0
1: getfield #3 // Field n:I
4: aload_0
5: getfield #3 // Field n:I
8: if_icmpeq 21
11: new #4 // class java/lang/AssertionError
14: dup
15: ldc #5 // String This statement is false
17: invokespecial #6 // Method java/lang/AssertionError."<init>":(Ljava/lang/Object;)V
20: athrow
21: return