Java 在这种情况下,是否永远不会抛出此断言错误?
首先是代码,来自JCIP清单和 我的意思是,在这种情况下不会抛出AssertionError,因为Thread.start()发生在担保之前。注释的System.out.printlns都打印main,这意味着主线程是,它通过在while(true)循环中的线程上创建并调用start生成所有后面的线程 由于这是创建并初始化Holder的线程,所有后续线程都可以安全地成为一个完全可见的Holder,因为有了before保证。我说得对吗 我甚至试着运行这段代码很长时间,没有断言错误 然而,如果main如下所示,那么我相信断言错误是可能的Java 在这种情况下,是否永远不会抛出此断言错误?,java,multithreading,concurrency,visibility,safe-publication,Java,Multithreading,Concurrency,Visibility,Safe Publication,首先是代码,来自JCIP清单和 我的意思是,在这种情况下不会抛出AssertionError,因为Thread.start()发生在担保之前。注释的System.out.printlns都打印main,这意味着主线程是,它通过在while(true)循环中的线程上创建并调用start生成所有后面的线程 由于这是创建并初始化Holder的线程,所有后续线程都可以安全地成为一个完全可见的Holder,因为有了before保证。我说得对吗 我甚至试着运行这段代码很长时间,没有断言错误 然而,如果ma
public static void main(String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().getName());
StuffIntoPublic t = new StuffIntoPublic();
new Thread(() -> t.initialize() ).start();
while (true) {
new Thread(() -> { t.holder.assertSanity(); }).start();
}
}
是的,这是安全的,因为
Thread#start
保证以前发生过。更详细地说:在线程#开始
之前发生的对任何变量的任何读/写(如果您愿意,我倾向于按程序顺序进行上述思考),也将在该线程内的任何操作之前发生(它是运行
方法)
事实上,如果之前没有发生过(允许重新排序),并且程序执行允许这些潜在的重新排序,那么这可能会中断并抛出错误。我甚至倾向于说,在弱内存模式下使用合适的CPU(假设您使用的是英特尔,这是一种强内存模式)可能会增加这种可能性,但我不确定
因此,据我所知,操作将按以下顺序进行:首先,发布引用将使用变量n
重新排序(之前没有发生过,因此这是允许的)。Thread1创建了一个Holder
的实例。Thread2看到发布的引用并调用该方法。它将变量n
读取为0
(请记住,发生了重新排序,并且n
尚未写入,因此默认值为0
),因此它会执行=代码>检查,但创建保持架的Thread1将n
写入12
,例如,在Thread2再次读取它之前(在!=n
部分)。所以这可能会失败
将值设置为final将解决这一问题,因为它引入了正确的内存障碍,或者发生在规则之前 你从哪里拿到的SafePublication
课程代码?我写了那个代码然后我不明白你的问题实际上,SafePublication
是不安全的,因为holder=newholder(42)
是不安全的发布。在SafePublication的主要方法中,是否可以抛出AssertionError?
public static void main(String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().getName());
StuffIntoPublic t = new StuffIntoPublic();
new Thread(() -> t.initialize() ).start();
while (true) {
new Thread(() -> { t.holder.assertSanity(); }).start();
}
}