浅析volatile域

作用

如果对共享变量除了赋值之外并不完成其他操作,那么可以将这些共享变量声明为volatile。

原理

volatile关键字为实例域的同步访问提供了一种免锁机制。如果声明一个域为volatile,那么编译器和虚拟机就知道该域可能被另一个线程并发更新。

private volatile boolean done;
public boolean isDone(){ return done};
public void setDone(){done = true};
当然也可以使用锁来实现:

private boolean done;
public synchronized boolean isDone(){return done;}
public synchronized void setDone(){done = true;}
相对来说,使用锁显得开销过大了,volatile就更合适。但是volatile变量不能提供原子性,例如方法
public void flipDone(){done = !done;}
不能确保翻转域中的值,不能保证读取、翻转和写入不被中断。
参考:《Java核心技术 卷1》 第14章:并发

不保证原子性

举个累加的例子

public class VolatileTest01 implements Runnable{
	private volatile static int count = 0;	//并不保证原子性
	
	public static void main(String[] args) {
		Runnable vt = new VolatileTest01();
		Thread t1 = new Thread(vt, "A");
		Thread t2 = new Thread(vt, "B");
		t1.start();
		t2.start();
		
	}

	@Override
	public void run() {
			for(int i = 0; i < 10000; i++){
				count++;
			}
			System.out.println(Thread.currentThread().getName() + "-->count = " + count);
		}
}
该段代码不能保证原子性,输出的结果不确定,我一次输出的结果如图:

如果使用锁的方法就可以保证原子性了

public class VolatileTest02 implements Runnable{
	private static int count = 0;	
	
	public static void main(String[] args) {
		Runnable vt = new VolatileTest02();
		Thread t1 = new Thread(vt, "A");
		Thread t2 = new Thread(vt, "B");
		t1.start();
		t2.start();
		
	}

	@Override
	public synchronized void run() {		//使用锁保证了原子性
		for(int i = 0; i < 10000; i++){
			count++;
		}
		System.out.println(Thread.currentThread().getName() + "-->count = " + count);
	}
}


每次输出的结果都为确定的:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值