最近在看《Java编程思想》,记录一些觉得有必要整理的内容。本篇就简要分析一下Java并发编程中遇到的volatile关键字。
并发编程中,我们通常会遇到以下三个概念:原子性、可视性以及有序性。
volatile关键词正式对应可视性这个概念。
可视性是指,当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看到修改的值。即便使用了本地缓存,volatile修饰的域也会立即被写入到主存中,而读取操作就是发生在主存中。
而相应地,非volatile域上的原子操作不必刷新到主存中去,因此其他读取该域的任务也不必看到这个新值。
然而,要区分原子性和可视性是不同的概念。volatile关键字能保证可视性但并不能保证操作的原子性。如果一个域的值依赖于它之前的值,例如递增一个计数器,或者某个域的值收到其他域的值的限制,例如Range类的lower和upper边界就必须遵循lower<=upper的限制,那么只用volatie修饰是不起作用的。保持原子性或说同步,第一选择应该是使用synchronized
关键字,同步也会导致向主存中刷新,因此synchronized
防护的方法或语句块内的域就不必使用volatile
修饰了。