Java——volatile关键字

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/beitacat/article/details/82354497

volatile,用来修饰变量,被修饰的变量将直接从线程公共的内存中取值。线程安全包含了可见性和原子性两方面。

每个线程拥有独立的私有内存,用于存放数据,线程从主内存中获取数据,放入私有内存中进行操作。若有多个线程同时操作同一个数据,该数据将被存放到多个私有内存中处理,处理完毕之后,返回到主内存的值可能就会存在不同,后返回的值会覆盖先返回的值:

int i = 1;

Thread A 执行 10次i++

Thread B 执行 100次i++,原本希望获取到的最终值是:i=110,但是由于线程互不干扰,线程各自每次修改的值都是私有内存中的数据,并没有修改主内存中的数据,并且线程之间也并不知道其他线程修改了该数据。最终线程执行完毕,返回到主内存的值要么是10,要么是100,比如A先执行完毕,将10赋值给主内存的i,然后B执行完毕,将100赋值给主内存的i。

当使用volatile修饰时,volatile int i = 1;此时,多个线程在操作同一个数据时,不会每次都操作赋值到私有内存的值,而是会直接从主内存中取最新的值。比如:

Thread A 执行 10次i++

Thread B 执行 100次i++,两个线程每次修改数据之后,会立马将值放回主内存,更新数据,其他线程也会直接从主内存取值,取到的也是最新的数据,线程之间能够互相发现值的改变,即实现了实例变量在多个线程间的可见性。

但是,并不能保证原子性。上面的例子结果并不能保证得到:i=110。因为没有用锁,变量依然在被多个线程同时操作修改。

比如:原本主内存中i=0,A将要修改i=1,但是还没有修改,B线程就获取了值,进行操作i=2,操作完毕之后将值返回给主内存,此时A线程被激活,修改i=1,覆盖了B的i=2。

volatile与synchronized区别:

  1. volatile只能保证可见性,不能保证原子性。synchronized原子性,可见性都能保证(会将私有内存中的数据和主内存的数据做同步);
  2. volatile只能修饰变量,synchronized修饰函数,代码块;
  3. 多线程访问volatile不会发生阻塞,synchronized会发生阻塞。

使用场景:

volatile最适用一个线程写,多个线程读的场合。如果有多个线程并发写操作,仍然需要使用锁或者线程安全的容器或者原子变量来代替。(摘自Netty权威指南)。用于多个线程执行读操作。

  • 对变量的写操作不依赖于当前值。
  • 该变量没有包含在具有其他变量的不变式中。

猜你喜欢

转载自blog.csdn.net/beitacat/article/details/82354497