问题描述
问题已经在之前发布,但没有提供真实的例子作品.因此,Brian 提到在某些条件下,AssertionError 可能发生在以下代码中:
The question has been posted before but no real example was provided that works. So Brian mentions that under certain conditions the AssertionError can occur in the following code:
public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if (n!=n)
throw new AssertionError("This statement is false");
}
}
当持有人像这样不正确地发布时:
When holder is improperly published like this:
class someClass {
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
}
我知道,在对象持有者的实例变量对另一个线程可见之前,对持有者的引用可见时会发生这种情况.因此,我制作了以下示例来激发这种行为,从而引发具有以下类的 AssertionError:
I understand that this would occur when the reference to holder is made visible before the instance variable of the object holder is made visible to another thread. So I made the following example to provoke this behavior and thus the AssertionError with the following class:
public class Publish {
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
public static void main(String[] args) {
Publish publish = new Publish();
Thread t1 = new Thread(new Runnable() {
public void run() {
for(int i = 0; i < Integer.MAX_VALUE; i++) {
publish.initialize();
}
System.out.println("initialize thread finished");
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
int nullPointerHits = 0;
int assertionErrors = 0;
while(t1.isAlive()) {
try {
publish.holder.assertSanity();
} catch(NullPointerException exc) {
nullPointerHits++;
} catch(AssertionError err) {
assertionErrors ++;
}
}
System.out.println("Nullpointerhits: " + nullPointerHits);
System.out.println("Assertion errors: " + assertionErrors);
}
});
t1.start();
t2.start();
}
}
无论我运行代码多少次,AssertionError 都不会发生.所以对我来说有几个选择:
No matter how many times I run the code, the AssertionError never occurs. So for me there are several options:
- jvm 实现(在我的例子中是 Oracle 的 1.8.0.20)强制所有线程都可以看到在对象构造期间设置的不变量.
- 这本书是错误的,我对此表示怀疑,因为作者是 Brian Goetz ... nuf 说
- 我在上面的代码中做错了
所以我的问题是:- 有没有人成功地引发过这种 AssertionError?用什么代码呢?- 为什么我的代码不会引发 AssertionError?
So the questions I have:- Did someone ever provoke this kind of AssertionError successfully? With what code then?- Why isn't my code provoking the AssertionError?
推荐答案
您的程序未正确同步,因为该术语由 Java 内存模型定义.
Your program is not properly synchronized, as that term is defined by the Java Memory Model.
然而,这并不意味着任何特定的运行都会表现出您正在寻找的断言失败,也不意味着您一定可以期望永远看到该失败.可能是您的特定 VM 恰好以一种结果证明永远不会公开该同步失败的方式处理该特定程序.或者它可能会证明虽然容易出现故障,但可能性很小.
That does not, however, mean that any particular run will exhibit the assertion failure you are looking for, nor that you necessarily can expect ever to see that failure. It may be that your particular VM just happens to handle that particular program in a way that turns out never to expose that synchronization failure. Or it may turn out the although susceptible to failure, the likelihood is remote.
不,您的测试没有为编写无法以这种特定方式正确同步的代码提供任何理由.你不能从这些观察中概括.
And no, your test does not provide any justification for writing code that fails to be properly synchronized in this particular way. You cannot generalize from these observations.
这篇关于布赖恩·戈茨 (Brian Goetz) 的不当出版物的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!