天天看点

《并发编程》--6.Java内存模型(JMM)的关键字volatile

Java的内存模型(JMM)都是围绕着原子性,有序性,可见性。一些特殊的场合下,需要用volatile等关键字保证这些特性。

当用volatile声明一个变量时,就相当于告诉虚拟机,这个变量极有可能在多个线程中修改。为了确保这个变量被修改后,程序的所有线程都能够意识到这个改动,虚拟机就必须采用一些特殊的手段,保证这个变量的可见性。

声明的代码如下:

static volatile int i = 0;
           

注意:volatile虽然能很大程度的维护原子性,但是不能替代锁

一下一个简单的demo即可说明

public class volatileMain1 {

	static volatile int i = 0;
	public static class Task implements Runnable {
		@Override
		public void run(){
			for(int k=0;k<10000;k++){
				i++;//如果是原子性的,最终的是为100000(10个线程累计加10)
					//实际是小于100000的
				    //证明volatile不能代替锁
			}
		}
		public static void main(String[] args) throws InterruptedException {
			Thread[] t = new Thread[10];
			for(int i = 0;i<10;i++){
				t[i] = new Thread(new Task());
				t[i].start();
			}
			for(int i=0;i<10;i++){
				t[i].join();
			}
			System.out.println(i);
		}
		
	}
}
           

实际的运行结果是小于100000的。。。

另外volatile也能保证数据的可见性和有序性,以后是一个简单的demo

public class volatileMain2 {
	private static boolean ready;
	private static String name;
	
	private static class ReaderThread extends Thread{
		@Override
		public void run(){
			while(!ready);//虚拟机在client模式下,由于JIT并没有做优化,主线程修改number,ReaderThread发现这个改动,退出程序
			              //虚拟机在server模式下,由于系统的优化,导致ReaderThread永远无法退出(因为readdy为false)
			System.out.println("I am "+name);
		}
	}

	public static void main(String[] args) throws InterruptedException {
		new ReaderThread().start();
		Thread.sleep(1000);
		name = "yemt";
		ready = true;
		Thread.sleep(10000);
	}
}
           

注意:可以使用Java虚拟机参数-server切换到Server模式

继续阅读