下面的代码是否违反线程内语义?
static Integer sync;
public static void main(String[] args) throws Exception {
Runnable r = new Runnable() {
@Override
public void run() {
sync = 6;
System.out.println("written thread 1");
try {
Thread.sleep(9999);
} catch (InterruptedException ex) {
Logger.getLogger(IO.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(sync);
}
};
Runnable t = new Runnable() {
@Override
public void run() {
sync = 2;
System.out.println("written thread 2");
try {
Thread.sleep(9999);
} catch (InterruptedException ex) {
Logger.getLogger(IO.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(sync);
}
};
Thread th1 = new Thread(r);
Thread th2 = new Thread(t);
th1.start();
th2.start();
}
演示
结果是:
written thread 1
written thread 2
2
2 //!!!! Is intra-thread semantic violates?
JLS在17.4说:
[…]如前所述,所有线程都需要遵守正确的Java程序的线程内语义。[…]
我认为线程内语义意味着线程将像程序中的单个线程一样工作。也就是说,由th1
分配的值仅对于th1
是可观察的,并且对于th2
是类似的。
我可能没有正确理解线程内语义概念?
问题是,你在这里得到了自己和"线程间"操作
线程间动作是由一个线程执行的动作,该动作可以被另一个线程检测到或直接影响。
而不是"线程内"操作。两个线程共享一个共同的内存位置(变量sync
),从一个线程设置值是一种效果,另一个线程可以检测到。"线程内"语义的描述说明
每个线程在隔离状态下的操作都必须由该线程的语义控制,,但每次读取所看到的值由内存模型确定除外。
(强调矿,来源)
线程内语义仅指线程之间不共享的变量。
因此,输出与Java内存模型(JMM)一致。
另一方面,您的程序没有正确同步,因为您有两个线程在向同一个静态变量(sync
)写入,因此程序可以同时产生输出(6,2)和(2,2),并且仍然实现JMM。