MST

星途 面试题库

面试题:Java多线程环境下可见性问题与锁机制的关系

阐述Java多线程编程中,锁机制(如synchronized关键字)是如何间接解决可见性问题的,以及与volatile关键字在解决可见性方面的异同点。
37.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

锁机制(如synchronized关键字)间接解决可见性问题

  1. 工作原理
    • 当一个线程进入synchronized块时,会从主内存中重新读取共享变量的值。
    • 当线程退出synchronized块时,会将共享变量的最新值刷新回主内存。
    • 这就确保了其他线程在进入synchronized块时能获取到最新的值,从而间接解决了可见性问题。例如:
public class SynchronizedVisibility {
    private static int count = 0;
    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            synchronized (SynchronizedVisibility.class) {
                count++;
            }
        });
        Thread thread2 = new Thread(() -> {
            synchronized (SynchronizedVisibility.class) {
                System.out.println("Count value: " + count);
            }
        });
        thread1.start();
        try {
            thread1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread2.start();
    }
}
  • 在上述代码中,线程thread1修改count变量,因为在synchronized块中,修改后会将count刷新回主内存。线程thread2进入synchronized块时,会从主内存读取count,从而保证了可见性。

synchronized与volatile在解决可见性方面的异同点

  1. 相同点
    • 两者都能解决多线程环境下的可见性问题。即当一个线程修改了共享变量,其他线程能够感知到这种变化。
  2. 不同点
    • 原子性
      • synchronized关键字既保证可见性,又保证原子性。例如,多个线程同时执行synchronized修饰的方法或代码块时,同一时间只有一个线程能执行,不会出现数据竞争导致的不一致问题。
      • volatile关键字仅保证可见性,不保证原子性。比如,对于volatile int i = 0;i++这样的操作在多线程环境下不是原子的,多个线程同时执行i++可能会导致结果与预期不符。
    • 使用范围
      • synchronized可以修饰方法、代码块,作用范围相对较灵活。可以针对类、对象实例进行加锁。
      • volatile只能修饰变量,作用范围相对单一。
    • 性能
      • synchronized是一种重量级锁,会导致线程上下文切换等开销,性能相对较低,特别是在竞争激烈的情况下。
      • volatile性能开销较小,因为它不会引起线程上下文切换,只是保证变量的可见性。