1.首先要明白一个概念 JAVA中主内存和线程工作内存的概念。
如果有一个static的变量,值会存储在主内存。如果多个线程访问这个变量,每个线程都会将变量的值拷贝到自己的工作内存,之后的操作就是针对自己工作内存里副本的操作,最后再写回主内存
明显,上面的操作非原子操作,会出现经典的多线程问题:
变量 i=6,线程A和B都对i进行加1操作,期待i为8,但是: 线程A访问 i, 线程A进行 i++操作 线程B访问 i, 线程B进行 i++操作 线程A更新i,i为7 线程B更新i,i为7
2. volatile关键字,告诉JVM,我访问的这个变量,不需要创建工作内存的副本,我要直接操作主内存上的变量,它涉及到 多线程里的可见性:
对于可见性,Java提供了volatile关键字来保证可见性。
当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
而普通的共享变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。
3. 但是,volatile依然无法保证原子性,在1中所说的情况依然会出现,所以volatile可以保证可见性,不能保证原子性
4. 那么原子性和可见性有什么区别呢?
原子性就是一个操作的执行是不能被打断的
可见性是一个操作的执行结果马上被其他操作所感知,区别于原子性是,不能保证本操作不被打断,只是本操作执行的结果能够被其他操作所感知
时间: 2024-10-25 15:07:00