刚开始学并发的时候总会在这里模糊不清,我觉得是概念没有理清楚。
1.首先我们看下什么叫做线程安全。
只有在线程共享某个变量或者一组变量时,我们才需要让这个变量或者这组变量线程安全,否则不需要去设计线程安全策略,因为这会损耗资源和性能。可以自己找下银行转账的例子帮助理解。
2.再来看volatile。假设volatile能够保证线程安全,那么它也只能保证被修饰的变量线程安全。然而事实上它不能保证被修饰变量线程安全。volatile语义有两个。
(1)可见性问题。它的本质是因为cpu修改某个变量的值并不是直接修改内存的,它会先修改cpu缓存对应的值,再把值刷回内存,这意味着写操作并不是原子操作。当cpu对cpu缓存的写操作已经完成,但是还没写回内存的这段间隔里,如果有其它线程去内存读这个变量,被volatile修饰的变量,它会强制cpu将这个cpu缓存的值先写回内存中,而未被volatile修饰的变量cpu则不会这么做。
(2)volatile第二个语义是禁止指令重排。
你看到的java代码和底层实际执行的指令的顺序是有可能是不一样的,因为jvm会对你写的代码进行一定范围内的优化,包括指令顺序的调整。具体的网上也有详细资料。