【261、volatile保证什么的?happens-before原则怎么理解的?】

69 阅读3分钟

volatile 关键字可以确保多个线程之间对变量的可见性(visibility),即一个线程修改了一个被 volatile 修饰的变量的值,其他线程可以立即看到这个变量的新值。

具体来说,使用 volatile 关键字修饰的变量在进行读写操作时,会直接从内存中读取或写入,而不会从线程的缓存中读取或写入。这就保证了不同线程之间对该变量的访问是同步的,避免了可能的数据竞争问题。

需要注意的是,volatile 关键字只能保证对单个变量的原子性操作,不能保证对多个变量的复合操作的原子性。如果需要对多个变量进行原子性操作,可以使用 synchronizedjava.util.concurrent.atomic 中的原子类。

happens-before 原则是 Java 中的一种多线程编程规则,用于指定不同线程之间操作执行的先后顺序。如果一个操作 a 在时间上发生在另一个操作 b 之前,那么我们说操作 a 发生在操作 b 之前,即 a happens-before b

这个原则主要用于解决由于指令重排等优化技术可能导致的并发问题。在 Java 中,只有在满足一定条件的情况下,指令重排才是合法的。其中一个条件就是不能改变程序的执行结果,即保证程序的执行顺序不变。

例如,在一个线程中对一个共享变量进行写操作,然后在另一个线程中对同一个变量进行读操作,如果在写操作之前添加了一个 happens-before 的关系,那么读操作就能够看到写操作的结果。具体来说,可以通过 synchronized 关键字或者 volatile 关键字来建立 happens-before 的关系。

简单来说,happens-before 原则保证了在多线程程序中,一个线程所做的操作在时间上的顺序对于其他线程是可见的,避免了可能的数据竞争和线程安全问题。

在 Java 中,下列情况下会产生 happens-before 关系:

  1. 程序顺序规则:一个线程中的每个操作 happens-before 该线程中的任何后续操作。
  2. 锁定规则:一个解锁操作 happens-before 任何后续对同一锁的加锁操作。
  3. volatile 变量规则:对一个 volatile 变量的写操作 happens-before 任何后续对该变量的读操作。
  4. 传递性规则:如果 A happens-before B,且 B happens-before C,则 A happens-before C。
  5. 线程启动规则:一个线程的启动操作 happens-before 该线程中的任何操作。
  6. 线程终止规则:一个线程中的任何操作 happens-before 其他线程检测到该线程已经终止。
  7. 线程中断规则:对线程 interrupt() 方法的调用 happens-before 被中断线程的代码检测到中断事件的发生。
  8. 对象终结规则:一个对象的初始化操作 happens-before 该对象的 finalize() 方法的开始。

理解 happens-before 原则可以帮助我们编写正确的多线程并发程序,避免出现数据竞争、死锁等问题。