Java SafeThread类中synchronized和volatile的作用?

rt.jar包里有个SafeThread类,类源码如下:

final class SafeThread extends Thread {
         private volatile boolean ran = false;

         public SafeThread(Runnable target) {
             super(target);
         }

         public final void run() {
             if (Thread.currentThread() != this) {
                 throw new IllegalStateException("The run() method in a"
                     + " SafeThread cannot be called from another thread.");
             }
             synchronized (this) {
                if (!ran) {
                    ran = true;
                }
                else {
                 throw new IllegalStateException("The run() method in a"
                     + " SafeThread cannot be called more than once.");
                 }
             }
             super.run();
         }
    }

为什么加了synchronized之后,还需要给ran变量加volatile呢,如果单例模式的双检查是为了防止指令重排,但这里初始状态就已经赋值了,应该不会存在指令重排的情况了吧

阅读 376
avatarAI BotBETA

在这个 SafeThread 类中,synchronizedvolatile 的作用是不同的。

synchronized 关键字在这里用于确保 run 方法在同一时间只能被一个线程执行。这可以防止多个线程同时访问和修改 ran 变量,从而确保 ran 变量的状态在任何时候都是一致的。

volatile 关键字在这里的作用主要是确保 ran 变量的可见性。在多线程环境中,每个线程都有自己的工作内存,每个线程对变量的修改都只存在于自己的工作内存中,而不是共享内存。volatile 关键字可以确保每次读取 ran 变量时,都会从主内存中获取最新的值,而不是从工作内存中读取。这样可以防止由于线程工作内存中的值过期而导致的不正确的结果。

关于你提到的双检查锁问题,这是针对单例类的初始化问题。在这个 SafeThread 类中,虽然 ran 变量在 SafeThread 实例初始化时就已经被赋值了,但是 run 方法在多线程环境中可能会被多个线程并发执行。在这种情况下,为了保证 run 方法中的代码逻辑在任何时候都只被一个线程执行,需要使用 synchronized 关键字。而 volatile 关键字则用于保证其他线程在调用 run 方法时可以看到 ran 变量的最新值。

总的来说,synchronizedvolatile 在这个类中的作用分别是保证多线程环境下的线程安全和保证变量的可见性。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏