Volatile关键字

Volatile关键字

通过该关键字保证不同线程对某个共享变量的可见性;

Volatile与synchronize区别

  1. Volatile只能修饰实例变量或者类变量,不能修饰方法、局部变量、方法参数、常量;
  2. synchronized关键字只能用于修饰方法或者代码块,不能修饰变量;
  3. Volatile修饰的变量可以为null,synchronized修饰的代码块的monitor不能为null;
  4. volatile不能保证原子性,synchronized是一种排他机制被其修饰的同步代码块不能被中途打断,因此是保证原子性的
  5. 两者都可保证有序性、可见性
  6. volatile不会使线程进入阻塞状态,后者会;

并发编程的三大特征

  • 原子性:在一次或者多次的操作中,要么所有的操作都全部得到执行并且不会受任何因素的干扰而中断,要么所有操作都不执行;比如:转账1000,有两个操作转账账户扣除1000,收款账户增加1000,这两个操作必须原子操作;

基本数据类型的读取赋值操作都是原子性,引用类型变量的读取和赋值操作也是原子性的;

(1)、多个原子性操作合在一起就不再是原子操作了;

比如:
x=10;(原子性)

  1. 执行线程首先将x=10写入工作内存
  2. 然后再 将其写入主内存

x=y;(非原子性)

  1. 首先把y的的值从主内存中读取,然后存入当前线程的工作内存之中(如果已经在工作内存中,直接从工作内存中读取)(原子性)
  2. 在工作内存中将x的值修改为y的值,然后将x的写入主内存中;(原子性)

将第一二步何在一起就不是原子性了;

(2)、简单的读取赋值操作是原子性的,将一个变量赋值给另一个变量不是原子性的
(3)、java内存模型只保证了基本读取和赋值的原子性,其他不保证;
(4)、如果要想使代码片段具备原子性,可以使用synchronize关键字或者JUC中的lock;如果要时基本类型自夹具备原子性,可以使用 java.util.concurrent.atomic.*包下的类;

Volatile关键字不具备原子性;

  • 可见性:当以一个线程修改了共享变量的值,另外的线程可以立即看到改变后的最新值;

保证可见性的方式:

  1. volatile修饰变量,对共享变量的写操作,在工作工作内存中完成后(其他线程必须重新从主存中获取最新值),会立即刷新到主内存中;
  2. synchronized关键字,保证同一时刻只有一个线程获得锁,然后执行同步方法,并且在释放锁之前,会将对变量的修修改刷新到主内存中;
  3. 通过JUC提供的显示锁,保证同一时刻只有一个线程获得锁,然后执行同步方法,并且在释放锁之前,会将对变量的修修改刷新到主内存中

Volatile关键字具备可见性;

  • 有序性:代码在执行时的先后顺序,java在编译器和运行期做了优化,代码执行的先后顺序可能和我们编写代码的先后顺序不一致(这叫做指令重排序)来提高效率,但最终的结果是相同的;

需要注意:在单线程中,重排序始终能保证运算结果一致,但是在多线程中就不能保证了;

java提供了三种保证有序性的方式:

  1. volatile
  2. synchronized
  3. 显式锁

后两者采用同步的方式,同步代码在执新时与单线程一样,自然能保证有序性;

Volatile关键字具备有序性;

Volatile关键字的语义

被Volatile修饰的类变量和实例变量具备如下语义:

  1. 当一个线程修改了被volatile修饰的变量的值,其他线程会立即得到最新的值;
  2. 禁止对指令重排序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值