java - java中的同步和代码重新排序

标签 java multithreading jvm synchronized java-memory-model

在某些链接中,给出了同步块(synchronized block)内的代码重新排序是可能的,而其他一些站点则告诉这是不可能的。您能否举个例子来描述使用synchronized时代码重新排序实际发生的情况?

最佳答案

有两种可能的重新排序:

  • 同步块(synchronized block)之前或之后的语句可以移动到同步块(synchronized block)内部(当然前提是它们不在不同的同步块(synchronized block)中) - 有时称为 the "roach motel" principle
  • 只要修改顺序一致,同步块(synchronized block)内的语句就可以重新排序(即,从与该 block 共享先发生关系的其他代码中看不到效果)

但更重要的是:如果您的代码正确同步,这些重新排序不会影响程序的执行,这是您应该关心的。

示例(所有变量最初为 0):

主题1:

a=1;
synchronized(lock) {
    b=1;
    c=1;
}
d=1;

线程2:

synchronized(lock) {
    if (a==1) print(b); // can print 0 or 1
    if (b==1) print(a)/print(c); // always prints 1
    if (b==1) print(d); // can print 0 or 1
    if (d==1) print(a)/print(b)/print(c); // always prints 1
}

特别是,将 d=1 移至 c=1 之前或将 a=1 移至 b=1 是允许的,因为线程 2 无法观察到它,因为线程 1 执行的同步块(synchronized block)看起来像线程 2 的原子操作。

另一方面,不使用相同锁的线程将能够观察到这些重新排序。

关于java - java中的同步和代码重新排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18929518/

相关文章:

java - dispatchKeyEvent 在 Unity 中不触发 - native Android 插件

java - 为什么Hadoop FTPFileSystem.listStatus(Path path)不起作用?

java - OpenJDK 客户端 VM - 无法分配内存

java - JVM内存管理和垃圾收集书?

java - 反射可以改变字段的声明类型吗

java - 我无法在 Java 程序(swing)中的面板/ Canvas /窗口上绘制图形。有任何想法吗?

java - 什么是 NullPointerException,我该如何解决?

java - 重写 SwingWorker 中的 process() 方法

Java 多线程 - 避免重复的请求处理

tomcat - 线程和JMS哪个更好?