java - 同步方法在停止一个线程和另一个线程方面的重要性是什么?

标签 java multithreading synchronization synchronized

从《Effective java》一书中,我有以下著名的从另一个线程停止一个线程的代码

 public class StopThread {
     private static boolean stopRequested;
     private static synchronized void requestStop() {
          stopRequested = true;
     }
     private static synchronized boolean stopRequested() {
          return stopRequested;
     }
     public static void main(String[] args)
                            throws InterruptedException {
          Thread backgroundThread = new Thread(new Runnable() {
               public void run() {
                   int i = 0;
                   while (!stopRequested()) {
                       i++;
                   }
               }
          });
          backgroundThread.start();
          TimeUnit.SECONDS.sleep(1);
          requestStop();
     }
}

那里写了一行“同步无效,除非同时读写 操作是同步的。“但是很明显,如果我们不将 synchronized 关键字与 requestStop 方法一起使用,代码将正常工作,即,它几乎终止1 秒后这是期望的。这里还有一件事是,如果我们不同步这两个方法,我们将(很可能)由于代码优化而进入无限循环。所以我的问题是:-
1.如果我们不同步“stopRequested”方法,在什么情况下会如何以及在什么情况下出错?尽管在这里,如果我们不同步它,程序会按预期运行,即,它会在大约 1 秒内终止。
2.synchronized关键字是否会强制VM每次停止优化?

最佳答案

1.如果我们不同步“stopRequested”方法,在什么情况下会如何以及在什么情况下出错?尽管在这里,如果我们不同步它,程序会按预期运行,即,它几乎在1秒

如果 JVM 决定优化后台线程的 run 方法中的代码,事情可能会出错。 JVM 可以重新排序 stopRequested() 的读取以进行优化,因为它可能永远不会再次调用 stopRequested() 方法。但现在几乎所有 JVM 实现都会处理这个问题,因此如果不将 stopRequested 设置为同步,您的代码仍然可以正常运行。这里还需要注意的是,如果不使 stopRequested 同步,则其他非同步线程可能不会立即看到对 stopRequested boolean 变量所做的更改。仅当您使用同步时,其他线程才能立即检测到任何更改,因为同步方法的条目会清除缓存并从内存中加载新鲜数据。这种对内存变化的即时检测在高度并发的系统中非常重要

2)synchronized关键字每次都会强制VM停止优化吗?

Synchronized 关键字不会强制 VM 停止优化,但会使其遵守下面列出的内容。 VM 仍然可以进行优化,但它必须处理以下事情。 同步有效地执行以下操作:-

  1. 它保证发生在关系之前。如果一个操作发生在另一个操作之前,则第一个操作对第二个操作可见并且排序在第二个操作之前。

  2. 它保证了内存可见性,即在同步块(synchronized block)退出之前,可以缓存的 block 内完成的所有修改都会立即刷新,这会导致任何其他同步线程立即看到内存更新。这对于高度并发的系统非常重要。

关于java - 同步方法在停止一个线程和另一个线程方面的重要性是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25427716/

相关文章:

iphone - 我在哪里可以找到有关 IOS 日历同步的好教程?

asynchronous - 如何在 UWP 中创建同步新闻源

javascript - 如何同步调用Q函数

java - Java 中的合法注释内容导致错误

java - 如何获取 Facebook 登录用户的雇主详细信息

java - 如果未设置某个值,如何抛出编译时异常。

Java 运行在 vscode 中无法运行

iphone - GCD 串行队列是否使用所有 CPU 内核?

java - 多线程和锁

python - 处理来自多个进程的单个文件