跟着实例学习java多线程5-初识volatile变量

同步机制可以保证原子操作和内存可见性,但是同步机制对变量的访问性能是我们不得不考虑的问题,java语言提供了一种弱同步机制,volatile变量。

它的原理大致是这样的,当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量总会返回最新写入的值。(参考《java并发编程实践》一书)

让我们来看一个实例:

package com.home.thread;
/**
 * @author gaoxu
 * 
 */
public class ThreadStart {

 private static class ReaderThread extends Thread{
 
  public void run(){
   SafeThread.setNumber(1);
  }
 }
 private static class ReaderThread1 extends Thread{
  public void run(){ 
	long start = System.currentTimeMillis();
    System.out.println("="+SafeThread.getNumber());
    long endTime = System.currentTimeMillis()-start;
    System.out.println("所用时间:"+endTime);
  }
 }
 
 public static void main(String[] para){
  
  new ReaderThread().start();
  new ReaderThread1().start();
 }
}


package com.home.thread;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author gaoxu
 * 
 */
public class SafeThread {
	volatile static int number;
		
	public  static  int getNumber() {
			return number;
	}

	public  static  void setNumber(int number) {
		
		SafeThread.number = number;
	}
	
}


这段代码的运行结果是 1 ,也就是说getNumber保证获取到的都是number变量最新的内存值,这都是volatile的功劳,我们可以把对volatile变量的访问想象成是synchronized的set和get操作(虽然同步远比volatile的内存可见性强),volatile的使用看似很方便,但是它的使用是有局限性的。

volatile变量的使用只能保证变量的内存可见性,不能保证变量的原子性,所以volatile变量的使用有如下条件:

        对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。

        该变量不会与其他的状态变量一起纳入不变条件中。

        在访问变量时不需要加锁。

我们看到上面代码的例子完全符合他的这些条件,所以这个例子是完全可以使用volatile的。

另外我们也在代码中加了测试时间的代码:

每种方式运行10遍。

得出的结论是使用volatile变量比同步平均快1毫秒。(精确度不高)








郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。