我只是想检查一下我对JMM的线程启动同步规则的理解是否正确:
是否仅仅因为下面的同步顺序,下面的Java程序必须打印"num:1 m_i:2 " ?
http://java.sun.com/docs/books/jls/third_edition/html/memory.html 17.4.4
启动一个线程的动作与它启动的线程中的第一个动作同步。
public class ThreadHappenBefore {
static int num;
int m_i;
public static void main(String[] args) {
final ThreadHappenBefore hb = new ThreadHappenBefore();
num = 1;
hb.m_i = 2;
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("num:"+num);
System.out.println("m_i:"+hb.m_i);
}
}).start();
}
}
在给定线程中,如果前面的代码对后面的代码有影响,则保证在其他代码之前编写。因为线程开始在赋值之后被编码为, 和赋值影响 print语句的结果,这些赋值对于打印它们的代码是"可见的"(即发生在它们之前)。 但是,当从另一个线程查看时,对执行顺序的效果没有这样的保证 EDITED(感谢评论) 对上面的重新排序进行了细化(粗体)
我不认为你这里有同步问题由于代码顺序,您将得到您期望的结果。如果有多个线程引用相同的源
到目前为止,除了Stephen C在评论中发表了正确的答案:线程的创建(start()而不是new thread()!)确保了happens-before关系。
如果不是这种情况,JVM可以很容易地重新排序指令,只要它能保证自己的线程不会看到差异。
可以肯定的是,在每一种具有合理多线程内存模型的语言中,对于这种情况都会有一些内存障碍,因为否则你无法可靠地将参数传递给线程。
不,由于17.4.5节中的"happens-before"关系,它打印了正确的内容。如果你看下一节的讨论,它也清楚地说明:
线程上的start()调用发生在线程中的任何操作之前启动线程。
而且:
如果x和y是同一个线程的动作,并且x在y之前程序顺序,然后hb(x, y)。
因此这两个赋值保证发生在线程的读操作之前。
您的示例中没有同步
什么 '同步顺序'?这里没有同步。这只是普通的执行命令。所有的赋值都发生在线程启动之前。