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之前的代码也会被看到。
本文介绍了Volatile关键字的作用,包括防止可见性问题和重排序,以及其作为轻量级同步机制的特点。Volatile适用于简单的赋值场景,但不适用于如a++这样的复合操作。与Synchronized相比,Volatile不提供原子性,但在某些场景下可作为其替代品。文章还讨论了Synchronized的特性,包括保证原子性和可见性,并指出Volatile是轻量级的同步选项。
24万+

被折叠的 条评论
为什么被折叠?



