Volatile关键字的作用:
预防可见性问题,重排序问题。
Volatile是一种同步机制,比synchronized或者Lock相关类更轻量,因为使用Volatile并不会发生上下文切换等开销很大的行为。
一个变量被修饰成volatile,JVM就知道了这个变量可能会被并发修改。
但是,volatile是一个轻量级的,对应的能力也小,无法像synchronized一样能够对变量进行原子保护。volatile仅在很有限的场景下才能发挥作用。
案例: 不适用于多线程a++计数。
案例2: boolean flag ,如果一个共享变量自始至终只被各个线程赋值,而没有其他的操作,那么就可以用volatile来代替synchronize或者代替原子变量,因为赋值自身是有原子性的,而volatile又保证了可见性,所以就足以保证线程安全。
注意:这个赋值是单纯的赋值,不能依赖前提条件。
package JMM; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; /** * @program:多线程和IO * @descripton: * @author:ZhengCheng * @create:2021/9/28-16:23 **/ public class WithVolatile implements Runnable{ volatile boolean flag = true; AtomicInteger real = new AtomicInteger(); public static void main(String[] args) throws InterruptedException { WithVolatile v = new WithVolatile(); Thread thread1 = new Thread(v); Thread thread2 = new Thread(v); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println(v.flag); System.out.println(v.real); } @Override public void run() { for (int i = 0; i < 10000; i++) { setFlag1();//correct; //setFlag2();//不对 real.incrementAndGet(); } } private void setFlag1(){ flag = false; } //不适用 private void setFlag2() { flag = !flag; } }
首先我们应当知道,volatile有什么样的作用。Volatile有如下两点作用
1.可见性,保证在读取一个volatile变量之前,需要先使相应的本地缓存失效,这样就必须到主内存读取最新值,写一个volatile属性会立即刷入到主内存。
2.禁止指令的重排序优化:解决单例双重锁乱序问题
Volatile的适用场景:
1.单纯的赋值场景 (注意,a++并不适合!)
明明volatile可以保证我们读取到最新值,那为什么会有a++问题呢?
因为我们知道,在JMM里,Volatile只保证我们读的值是正确的,但是假设此时T1和T2都读到a=1,在发生各自线程的自增之后,a=2,尽管其迅速的刷入了内存之中,但是我们得到的还是a=2,使得++操作少了一次。
2.触发器
那么Volatile和Synchronized有什么关系?
Volatile可以看做是轻量级的Synchronized:如果一个共享变量自始至终只有赋值操作,而没有复杂操作,那么就可以用volatile来代替synchronized来代替原子变量,因为赋值自身是有原子性的,而volatile又保证了可见性,在仅仅赋值的多线程的操作里,是足够保证线程安全的。
Volatile小结
1.volatile修饰符使用场景(2个)
2.volatile的读写操作是无锁的,不能像synchronized一样,所以它没有提供原子性和互斥性,导致volatile++是不安全的。但也正因为无锁,不需要花费时间在释放锁上,其花费是很低的。
3.volatile只能作用在属性上,而不像synchronized可以作用与一个方法上。
4.volatile保证了可见性的问题,在JMM得规范下,可以直接刷入主存。
5.volatile提供了happens-before,只要 写入了,就一定能够读到最新值。
6.volatile可以使得long和double的赋值是原子的。
Synchronized的理解
1.Synchronized不仅保证了原子性,还保证了可见性。
2.Synchronized不仅让被保护的代码安全,还近朱者赤。synchronized之前的代码也会被看到。