Java之多线程内存可见性_2(volatile不能保证原子性)

以下内容在慕课网-->细说Java多线程之内存可见性

volatile不能保证原子性


public class VolatileDemo{
	private volatile int number = 0;
	
	public int getNumber(){
		return this.number;
	}
	
	public void increase(){
		this.number++;
	}
	
	public static void main(String[], args){
		final VolatileDemo volDemo = new VolatileDemo();
		for(int i=0; i<500;i++)
		{	
			new thread(new Runnable(){
				public void run(){
					volDemo.increase();
				}
			}).start();
		}


		//如果还有子线程在运行,主线陈就让出cpu资源,
		//知道所有的子线程都运行完了,主线程再继续往下执行
		while(Thread.activiCount() > 1){
			Thread.yield();
		}
		
		System.out.println("number:" + volDemo.getNumber());
	}
}




实际执行结果不一定是500
因为:不能保证原子性,可能多个线程交叉执行

public void increase(){
		this.number++;
	}


number++  不是原子性
如:
number = 5
1.线程A读取number的值
2.线程B读取number的值
3.线程B执行加1操作
4.线程B写入最新的number的值
主内存:number = 6
线程B工作内存:number = 6
线程A工作内存:number = 5
5.线程A执行加1操作
6.线程A写入最新的number值,主内存的number = 6
7.整个过程2次number++实际上只加了1

解决方案:
保证number自增操作的原子性:
1.使用synchronized关键字
2.使用ReentrantLock(java.until.concurrent.locks包下, jdk1.5)
3.使用AtomicInterger(vava.util.concurrent.atomic包下, jdk1.5)


使用synchronized解决
修改:
1.
private volatile int number = 0; 修改为private int number = 0;


2.
public void increase(){
synchronized(this){
this.number++;
}
}



使用ReentrantLock解决 : 
修改:
1.增加  
private Lock lock = new ReentrantLock();

2.
public void increase(){
lock.lock();//加锁
try{   //推荐写法
   this.number++;
}finally{//锁内部操作可能会抛出一些异常,所以保证锁一定能被释放
   lock.unlock();//解锁
 } 
}

volatile适合场合
要在多线程中安全的使用volatile变量,必须同时满足”

1.对变量的写入操作不依赖其当前值(改变后的值不能与之前的值有关系)
如:不满足:number++  count = count*5等
满足:boolean变量、记录温度变化的变量等

2.该变量没有包含在具有其他变量的不变式中(有多个volatile变量,每个volatile变量状态独立于其他volatile变量)
如:程序中有2个volatile变量low,up 
不满足:不变式low<up

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值