在多线程并发编程的过程中,执行重排序
有时候会造成错误的后果,比如一个线程在main
线程中调用setFlag(true)
的前边修改了某些程序配置项,而在t1
线程里需要用到这些配置项,所以会造成配置缺失的错误。但是java给我们提供了一些抑制指令重排序的方式。
1.同步代码抑制指令重排序
将需要抑制指令重排序的代码放入同步代码块中:
在获取锁的时候,它前边的操作必须已经执行完成,不能和同步代码块重排序;在释放锁的时候,同步代码块中的代码必须全部执行完成,不能和同步代码块后边的代码重排序。
2.volatile变量抑制指令重排序
public class Reordering { private static volatile boolean flag; private static int num; public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { while (!flag) { Thread.yield(); } System.out.println(num); } }); t1.start(); num = 5; flag = true; } }
具体抑制重排序的规则如下:
- volatile写之前的操作不会被重排序到volatile写之后。
- volatile读之后的操作不会被重排序到volatile读之前。
- 前边是volatile写,后边是volatile读,这两个操作不能重排序。
3.final变量抑制指令重排序
具体的规则就这两条:
- 在构造方法内对一个final字段的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。
- 初次读一个包含final字段对象的引用,与随后初次读这个final字段,这两个操作不能重排序。
原文地址:https://www.cnblogs.com/hongchengshise/p/10409941.html
时间: 2024-11-08 20:54:00