volatile使用

volatile关键字的主要作用是使变量在多个线程间可见

JDK1.5开始对Thread进行了优化,对每个线程加了一块独立的内存空间。这个空间用于存放在thread中使用到的主线程中变量的副本,在线程运行过程中,直接在变量副本中操作,这样可以提高代码执行的效率。在下面代码中isRunning在线程执行过程中会使用,因此会将这个变量的副本放到线程独立的内存空间中。

public class RunThread extends Thread{

	//volatile
	private boolean isRunning = true;
	private void setRunning(boolean isRunning){
		this.isRunning = isRunning;
	}
	
	public void run(){
		System.out.println("进入run方法..");
		int i = 0;
		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");
	}
}

在Eclipse中console输出如下



isRunning使用volatile成员变量修饰,即private volatile boolean isRunning = true;则当变量改变时,会强制线程执行引擎去主内存里读取




下面例子,10个线程对一个静态变量进行操作,最终的结果不一定是10000

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 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[10];
		for (int i = 0; i < 10; i++) {
			arr[i] = new VolatileNoAtomic();
		}
		
		for (int i = 0; i < 10; i++) {
			arr[i].start();
		}
	}
}

Eclipse的console输出,运行结果如下图



为保证操作的原子性,做如下修改:

1.

//private static volatile int count;
private static AtomicInteger count = new AtomicInteger(0);//具备原子性

2.

//count++ ;
count.incrementAndGet();

run as -- java application,运行结果如下图:



volatile可以实现在多个线程之间的可见性,但是却不具备同步性(也就是原子性),可以算是一个轻量级的synchronized,性能要比synchronized强很多,不会造成阻塞(在很多开源的架构里,比如netty的底层代码就大量使用volatile,可见netty性能一定是非常不错的)。注意:一般volatile用于只针对于多个线程可见的变量操作,并不能代替synchronized的同步功能。要实现原子性建议使用atomic类的系列对象,支持原子性操作(注意:atomic类只保证本身方法原子性,并不保证多次操作的原子性)

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicUse {

	private static AtomicInteger count = new AtomicInteger(0);
	
	//多个addAndGet在一个方法内是非原子性的,需要加synchronized进行修饰,保证4个addAndGet整体原子性
	/**synchronized*/
	public synchronized int multiAdd(){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			count.addAndGet(1);
			count.addAndGet(2);
			count.addAndGet(3);
			count.addAndGet(4); 
			return count.get();
	}
	
	
	public static void main(String[] args) {
		
		final AtomicUse au = new AtomicUse();

		List<Thread> ts = new ArrayList<Thread>();
		for (int i = 0; i < 10; i++) {
			ts.add(new Thread(new Runnable() {
				@Override
				public void run() {
					System.out.println(au.multiAdd());
				}
			}));
		}

		for(Thread t : ts){
			t.start();
		}
	}
}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值