JUC并发编程--Volatile(二)

一、引言

   今天跟小编一起学习下Java轻量级的同步机制锁Volatile~


二、目录 

一、引言

二、目录 

三、什么是 Volatile ?

四、Volatile 特性

4.1 可见性

4.2 原子性

4.3 禁止指令重排

五、Volatile 和 synchronized 区别 ?

六、拓展

七、总结


三、什么是 Volatile ?

Volatile 是Java虚拟机提供 “轻量级的同步机制

Volatile 三大特性:

  • 1、保证的可见性
  • 2、不保证原子性
  • 3、禁止指令重排

四、Volatile 特性

 4.1 可见性

可见性:创建两条线程,共享同一个变量,一条线程更新了变量,会及时刷新回主内存。以保证其他线程能立即得知变量的最新值。

/**
 * @Author WangYan
 * @Date 2023/3/13 15:11
 * @Version 1.0
 * 测试 Volatile 可见性
 * 可见性: 创建两条线程,共享同一个变量,一条线程更新了变量,会及时刷新回主内存。以保证其他线程能立即得知变量的最新值。
 * 注意: System.out.println(); 底层方法被 synchronized 锁修饰,会保证可见性
 */
public class Test01 {

    private volatile static int num = 1;

    public static void main(String[] args) throws InterruptedException {

        new Thread(() -> {
            while (num == 1){

            }

        }).start();

        TimeUnit.SECONDS.sleep(1);

        num = 0;
    }
}

4.2 原子性

原子性: 要么全部成功,要么全部失败!

/**
 * @Author WangYan
 * @Date 2023/3/13 16:20
 * @Version 1.0
 * 测试 Volatile 原子性
 * 原子性: 要么全部成功,要么全部失败!
 */
public class Test02 {

    private volatile static int num = 0;

    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = () -> {
            for (int i = 0; i < 1000; i++) {
                // 模拟多条线程执行 num++,以测试原子性
                num++;
            }
        };

        List<Thread> list = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            Thread thread = new Thread(runnable);
            thread.start();
            list.add(thread);
        }

        for (Thread thread : list) {
            // 线程值进行累加
            thread.join();
        }

        System.out.println(num);
    }
}

运行结果:

正确结果应该是 50000,输出的是49934。明显是有问题,可以证实:Volatile 不保证原子性 

4.3 禁止指令重排

JMM要求有序性

计算机在执行程序时,为了提高性能,编译器和处理器常常会做指令重排,一把分为以下3种

单线程: 环境里面确保程序最终执行结果和代码顺序执行的结果一致.(单线程不用关心指令重排)

处理器在进行重新排序是必须要考虑指令之间的数据依赖性

多线程: 环境中线程交替执行,由于编译器优化重排的存在,两个线程使用的变量能否保持一致性是无法确定的,结果无法预测

源码写的顺序不见得和编译的指令顺序一样

例子:

public void mySort(){
    int x=11;//语句1
    int y=12;//语句2
    x=x+5;//语句3
    y=x*x;//语句4
}

编译后的可能为顺序:

1234

2134

1324

问题:

请问语句4 可以重排后变成第一条码?

答:因为存在数据的依赖性 ,所以语句4 没办法排到第一个

五、Volatile 和 synchronized 区别 ?

  • 1、Volatile 保证可见性,但是不保证原子性
  • 2、性能方面,synchronized关键字是防止多个线程同时执行一段代码,就会影响程序执行效率,而volatile关键字在某些情况下性能要优于synchronized。

但是要注意voliate关键字是无法替代synchronized关键字的,因为volatile关键字无法保证操作的原子性。

六、拓展

使用JUC原子类包,保证原子性操作,效率比Lock和Sync 锁更高!

代码:

/**
 * @Author WangYan
 * @Date 2023/3/13 17:03
 * @Version 1.0
 * 测试 保证原子性
 * 使用JUC原子类包,保证原子性操作,效率比Lock和Sync 锁更高!
 */
public class Test02Atom {
    private static AtomicInteger num = new AtomicInteger();

    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = () -> {
            for (int i = 0; i < 1000; i++) {
                // 模拟多条线程执行 num++,以测试原子性
                num.incrementAndGet(); // 底层是 sun.misc 包,CAS
            }
        };

        List<Thread> list = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            Thread thread = new Thread(runnable);
            thread.start();
            list.add(thread);
        }

        for (Thread thread : list) {
            // 线程值进行累加
            thread.join();
        }

        System.out.println(num);
    }
}

运行结果:

 输出结果50000.可以证实:保证原子性

七、总结

 

拜拜~

有任何问题欢迎大家指出~

Thank You !

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逸航不吃瓜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值