volatile关键字

volatile概念

volatile关键字主要作用就是在多个线程之间可见,当一个变量被定义为volatile之后,就可以保证此变量对所有线程的可见性,即当一个线程修改了此变量的值的时候,变量新的值对于其他线程来说是可以立即得知的。可以理解成:对volatile变量所有的写操作都能立刻被其他线程得知。但是这并不代表基于volatile变量的运算在并发下是安全的,因为volatile只能保证内存可见性,却没有保证对变量操作的原子性

 

实例
public class RunThread extends Thread{

	private  boolean isRunning = true;
	private void setRunning(boolean isRunning){
		this.isRunning = isRunning;
	}
	
	public void run(){
		System.out.println("进入run方法..");
		while(isRunning == true){
			//..
		}
		System.out.println("线程停止");
	}
	
	public static void main(String[] args) throws InterruptedException {
		RunThread rt = new RunThread();
		rt.start();
		Thread.sleep(1000);
		rt.setRunning(false);
		System.out.println("isRunning的值已经被设置了false");
		Thread.sleep(1000);
		System.out.println(rt.isRunning);
	}
	
	
}
结果: 进入run方法..
isRunning的值已经被设置了false
false

 结果分析:isRunning 被设置成false,但是代码一直在执行中,并没有打印出“线程停止”,按理说isRunning 被设置成false,跳出while循环,但是没有,为什么?其实这是jdk的原因

在java中执行线程的时候,jdk都会单独的分配一块空间,但是在jdk 1.5以后,对于每一个线程做了一个优化,对每一个线程加了一个独立的内存空间,这个空间装什么内容呢?去装主内存中的一些引用(就是当前线程锁使用到的一些引用变量),将主内存中的这些变量(它的副本)拷贝到自己的这块区间中去,然后线程在运行的过程中就是去这块区间取他的副本,这样jdk是为了提高线程执行的效率。

线程在执行过程中,他会找自己独立的那块空间,跟他交互,而调用的isRunning 被设置成false,只是将主内存中值改变掉,但是线程锁依赖的那块独立内存空间中的变量值并没有改变,所以依然是true,如果想要改变,变量声明成可见性,用volatile修饰,当isRunning 值改变的时候,会强制线程执行引擎去主内存中读取。

 

 

变量用volatile 修饰 执行
private volatile boolean isRunning = true;

结果:
进入run方法..
isRunning的值已经被设置了false
true
线程停止

 volatile具备可见性,但是不具备原子性 

 

/**
 * volatile关键字不具备synchronized关键字的原子性(同步)
 *
 */
public class VolatileNoAtomic extends Thread{
	private static volatile int count;
	//private static AtomicInteger count = new AtomicInteger(0);
	private static void addCount(){
		for (int i = 0; i < 1000; i++) {
			count++ ;
			//count.incrementAndGet();
		}
		System.out.println(count);
	}
	
	public void run(){
		addCount();
	}
	
	public static void main(String[] args) {
		
		VolatileNoAtomic[] arr = new VolatileNoAtomic[100];
		for (int i = 0; i < 10; i++) {
			arr[i] = new VolatileNoAtomic();
		}
		
		for (int i = 0; i < 10; i++) {
			arr[i].start();
		}
	}
 	
}
结果:
 1361
2361
1361
3361
4361
5361
6361
7361
8361
9361

 分析: 10个线程,每个线程是1000,最终是10000,但是结果没有10000,因为volatile不具备原子性, 如何保证原子性,推荐使用原子类Atomic进行操作

 

public class VolatileNoAtomic extends Thread{
	//private static volatile int count;
	private static AtomicInteger count = new AtomicInteger(0);
	private static void addCount(){
		for (int i = 0; i < 1000; i++) {
			//count++ ;
			count.incrementAndGet();
		}
		System.out.println(count);
	}
	
	public void run(){
		addCount();
	}
	
	public static void main(String[] args) {
		
		VolatileNoAtomic[] arr = new VolatileNoAtomic[100];
		for (int i = 0; i < 10; i++) {
			arr[i] = new VolatileNoAtomic();
		}
		
		for (int i = 0; i < 10; i++) {
			arr[i].start();
		}
	}
 	
}
4000
4000
5000
4000
4000
9000
8000
7000
6189
10000

 最终结果是10000

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值