寿宁县建设局网站,上海建设执业资格注册中心网站,建设网站外包公司,东方cj网上购物商城1.内存可见性 当一个变量被声明volatile时,它会保证被修改的值被立刻更新到主内存中,不会优化到寄存器或缓存中 2.禁止指令重排序 针对被volatile修饰的变量的读写相关指令,是不能被重新排序的 代码演示
class Counter{public int flag;
}
public class Thread3 {public stati… 1.内存可见性 当一个变量被声明volatile时,它会保证被修改的值被立刻更新到主内存中,不会优化到寄存器或缓存中 2.禁止指令重排序 针对被volatile修饰的变量的读写相关指令,是不能被重新排序的 代码演示
class Counter{public int flag;
}
public class Thread3 {public static void main(String[] args) throws InterruptedException {Counter counternew Counter();Thread t1new Thread(()-{while (counter.flag0){//方便演示什么都不做}});Scanner scannernew Scanner(System.in);Thread t2new Thread(()-{counter.flagscanner.nextInt();});t1.start();t2.start();t1.join();t2.join();}
}上述代码,t1线程在循环检查flag值,成立就执行代码,t2线程更改count值,使得线程1检查结果不成立,测试发现在t2线程代码输入结果后,线程1代码还是不会停止,这是由于t1线程在一个无限循环中检查flag的值并且flag的更新对t1线程不可见因此t1线程可能会永远等待下去即使t2线程已经修改了flag的值。
使用volatile解决
class Counter{public volatile int flag; // 声明为 volatile
}
public class Thread3 {// ... 其他代码保持不变 ...
} 使用volatile后 内存可见性volatile关键字确保了对volatile变量的写操作对其他线程总是可见的。当t2线程更新counter.flag的值时这个更新会立即对其他线程如t1线程可见。这意味着t1线程在检查counter.flag的值时将总是看到t2线程所做的最新更新。禁止指令重排序volatile关键字还禁止了一些可能导致数据竞争的重排序。具体来说它确保了写volatile变量之前的所有读写操作不会被重排序到写操作之后同时确保了读volatile变量之后的所有读写操作不会被重排序到读操作之前。这确保了t2线程中的读取输入和更新flag的操作不会被重新排序从而避免了数据竞争和不一致的行为。 因此如果将Counter类中的flag字段声明为volatile那么t1线程将能够正确地看到t2线程对flag的更新并且不会因为指令重排序而导致数据竞争或不一致的行为。