volatile关键字

如果我们只是需要并发的访问一两个值就使用同步,就显得开销有点大,在Java中还提供了volatile关键字来保证线程安全。

Volatile的中文意思是易变的,不稳定的,作为java中的关键词之一,用以声明变量的值可能随时会被别的线程修改。

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

使用volatile修饰的变量会强制将修改的值立即写入主存,主存中值的更新会使缓存中的值失效(非volatile变量不具备这样的特性,非volatile变量的值会被缓存,线程A更新了这个值,线程B读取这个变量的值时可能读到的并不是是线程A更新后的值)。

2)禁止进行指令重排序。

原子性、可见性、有序性

Volatile支持可见性和有序性,不支持原子性。

原子性:原子性通常指多个操作不存在只执行一部分的情况,如果全部执行完成那没毛病,如果只执行了一部分,那对不起,你得撤销(即事务中的回滚)已经执行的部分。

可见性:当多个线程访问同一个变量x时,线程1修改了变量x的值,线程1、线程2…线程n能够立即读取到线程1修改后的值。

有序性:即程序执行时按照代码书写的先后顺序执行。在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。

volatile的原理和实现机制

观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令
  lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:
  1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
  2)它会强制将对缓存的修改操作立即写入主存;
  3)如果是写操作,它会导致其他CPU中对应的缓存行无效。

示例:
我们可以用前面那个银行转账的例子来感受一下volatile关键字的使用效果:

模拟账户–Account类:

public class Account {
	private String name;// 名字 
	private double money;//余额 
	//构造方法 
	public Account(String name,double money) { 
		this.name = name;
		this.money = money; 
	} 
	public String getName() {
		return name; 
	} 
	public void setName(String name) {
		this.name = name; 
	} 
	public double getMoney() { 
		return money; 
	} 
	public void setMoney(double money) {
		this.money = money; 
	} 
}

Account相当于我们的临界资源,其中的private double money是需要在线程之间共享的,如果我们不加任何并发控制,也不使用volatile关键字声明,肯定是会出现数据安全的问题,这个我们之前已经验证过了。

下面我们将这个字段加上volatile关键字声明:

public class Account {
	private String name;// 名字 
	private volatile double money;//余额 
	//构造方法 
	public Account(String name,double money) { 
		this.name = name;
		this.money = money; 
	} 
	public String getName() {
		return name; 
	} 
	public void setName(String name) {
		this.name = name; 
	} 
	public double getMoney() { 
		return money; 
	} 
	public void setMoney(double money) {
		this.money = money; 
	} 
}

运行结果:

在这里插入图片描述

经过多次的运行,以及对运行结果的分析,我们发现并没有出现数据安全性问题。

总结:

1、Volatile支持可见性和有序性,不支持原子性;sychronized支持可见性、有序性、原子性。

2、Volatile关键字声明变量后,不会进行指令重排序。

3、在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比sychronized关键字更轻量级的同步机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值