多线程编程(六)——volatile关键字和原子类

目录

一、有序性、可见性、原子性

1、有序性

2、可见性

3、原子性

二、volatile关键字的作用——可见性

1、Volatile关键字使用条件

2、Volatile关键字使用场景

3、Volatile关键字使用缺点

4、Volatile关键字和synchronized关键字的比较

5、volatile的非原子性

三、原子类——原子性

1、原子类使用场景

(1)多线程环境中统计次数和递增操作

(2)限制接口数量,超过数量进行熔断

2、CAS(比较并替换)操作和ABA问题

(1)CAS操作

(2)ABA问题

3、原子类Atomic的不安全性


一、有序性、可见性、原子性

1、有序性

多线程指令重排序:

指令重排分为硬件层面和虚拟机层面,此处只讲虚拟机层面

目的:解决内存操作速度慢于CPU操作速度所带来的CPU空置问题,尽可能充分利用CPU

表现形式:虚拟机会按照特定的规则将程序打乱,使得写在后面的程序可能会先执行,写在前边的程序可能会后执行。

2、可见性

所谓的可见性,是线程A可以读取到线程B修改后的变量的值,改变线程从私有工作内存取变量值的方式,强制线程从主内存取值。

3、原子性

原子是世界上最小的单位,具有不可分割的特性

二、volatile关键字的作用——可见性

关键字volatile的主要作用是使变量在多个线程中可见。通过使用volatile关键字,强制从公共内存中读取变量的值,不允许线程内部对变量进行缓存和重排序、不加锁、不阻塞,实现更轻量级的线程同步。

内存结构图:

1、Volatile关键字使用条件

(1)对变量的写操作不依赖于当前值

(2)该变量没有包含在具有其他变量的不变式中

2、Volatile关键字使用场景

(1)用于指示发生了一个重要的一次性事件,例如完成初始化或请求停机

(2)用作状态标志

状态标记的公有特性,通常只有一种状态转换:比如标志从false转换为true,然后停止

3、Volatile关键字使用缺点

只有在状态真正独立于程序内其他内容时才能使用Volatile,但大多数编程环境都不满足上述条件,因此使用volatile比使用锁更加容易出错(谨慎)

4、Volatile关键字和synchronized关键字的比较

1、多线程访问volatile不会发生阻塞,而synchronized会出现阻塞

2、volatile能保证数据的可见性,但不能保证原子性;而synchronized可以保证原子性和可见性。

注:线程安全包括原子性和可见性两个方面,java的同步机制都是围绕这两个方面来确保线程安全的。

5、volatile的非原子性

关键字volatile虽然实现变量在线程之间的可见性,但是不能保障同步性(原子性),所以执行的结果也是存在问题的。

测试代码如下:

public class MyThread extends Thread {

    public volatile static int count;

    private static void addCount() {
        for (int i = 0; i < 100; i++) {
            count++;
        }
        System.out.println("打印相加结果:" + count);
    }

    @Override
    public void run() {
        addCount();
    }

    public static void main(String[] args) {
        // 定义100个线程
        MyThread[] myThreads = 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

swadian2008

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

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

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

打赏作者

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

抵扣说明:

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

余额充值