volatile关键字还确保了应用中的可视性。如果讲一个域声明为volatile的,那么只要对这个域残生了写操作,那么所有的读操作
就都可以看到这个修改。即便使用了本地缓存,情况也确实如此,volatile域会立即被写入到主存中,而读取操作就发生在主存中。
在非volatile域上的原子操作不必刷新到主存中去,因此其他读取该域的任务也不必看到这个新值。如果多个任务在同时访问这个
域,那么该域也应该是volatile,否则,这个域就应该只能经由同步来访问。同步也会导致向主存中刷新,因此如果一个域完全有synchronized
方法或语句块来保护。那就不必将其设置为是volatile。
一个任务所做的任何写入操作对这个任务来说都是可视的,因此如果它只需要在这个任务内部可视,那么你就不需要将其设置为
volatile的。
当一个域的值依赖于他之前的值时(例如递增一个计数器),volatile就无法工作了。如果这个域的值受到其他的域的值的限制,那
么volatile也无法工作,例如Range类的lower和upper边界就必须遵循lower<=upper的限制
基本上,如果一个域可能会被多个任务同时访问,或者这些任务中至少有一个是写入任务,那么就应该将这个域设置为volatile的。
如果将一个域定义为volatile,那么它就会告诉编译器不执行任何移除读取和写入操作的优化。这些操作的目的是用线程中的局部变量
维护对这个域的精确同步。实际上,读取和写入都是直接针对内存的,而却没有被缓存。但是,volatile并不能对递增不是原子性操作
这一事实产生影响。
注意:使用volatile而不是synchronized的唯一安全的情况是类中只有一个可变的域。再次提醒,你的第一选择应该使用synchronized
关键字,这是最安全的方式,而其他所有方式都是有风险的
以上来至java编程思想