happens-before

第一个操作和第二个操作之间满足 happens-before 关系,那么第一个操作对于第二个操作一定是可见的,也就是第二个操作在执行时就一定能保证看见第一个操作执行的结果。

happens-before的规则

1、单线程规则
单线程中后面的语句都可以看见前面语句的执行结果,但是不意味着happens-before 关系的规则和重排序冲突,只要重排序后的结果依然符合 happens-before 关系,就不会限制重排序。例如语句 1 修改的是变量 a 的值,而语句 2 的内容和变量 a 无关,那么语句 1 和语句 2 依然有可能被重排序。当然,如果语句 1 修改的是变量 a,而语句 2 正好是去读取变量 a 的值,那么语句 1 就一定会在语句 2 之前执行了。
2、锁操作规则(synchronized 和 Lock 接口等)
线程 A 和线程 B 两个线程在同一个锁中那么,线程A 和线程B的操作符合happens-before的规则
3、volatile变量
如果变量被 volatile 修饰,那么每次修改之后,其他线程在读取这个变量的时候一定能读取到该变量最新的值
4、线程启动
主线程启动子线程时,子线程能看到主线程在启动子线程前的所有操作结果
5、线程join
线程A ,join等待线程B后,线程A能看到线程B run方法中执行的所有结果
6、中断规则
如果一个线程被其他线程interrupt,那么检测中断时一定能检测到该中断的发生
7、并发工具类原则

  • 线程安全的并发容器(如 ConcurrentHashMap)在 get 某个值时一定能看到在此之前发生的 put 等存入操作的结果。也就是说,线程安全的并发容器的存入操作 happens-before 读取操作。
  • 信号量(Semaphore)它会释放许可证,也会获取许可证。这里的释放许可证的操作 happens-before 获取许可证的操作,也就是说,如果在获取许可证之前有释放许可证的操作,那么在获取时一定可以看到。
  • Future:Future 有一个 get 方法,可以用来获取任务的结果。那么,当 Future 的 get 方法得到结果的时候,一定可以看到之前任务中所有操作的结果,也就是说 Future 任务中的所有操作 happens-before Future 的 get 操作。
  • 线程池:要想利用线程池,就需要往里面提交任务(Runnable 或者 Callable),这里面也有一个 happens-before 关系的规则,那就是提交任务的操作 happens-before 任务的执行。