学习volatile

volatile关键字的特性

  1. 保证代码执行的有序性
    1. 内存屏障
  2. 可见性
    1. MESI
    2. 缓存一致性协议
  3. 但是volatile不能保证程序的原子性

 在下面这个例子里,count++表示了取值,计算和存储三个步骤,指的是不能保证这三个步骤的原子性,虽然count值可见,但是整个计算过程volatile不能保证。

package juc.volatil;

import java.util.ArrayList;
import java.util.List;

//volatile的不能保证原子性
public class T2 {
private /*volatile*/ int count = 0;
public synchronized void m() {
	for (int i = 0; i < 10000;i++) count++;
	
}
public static void main(String[] args) {
	List threads = new ArrayList();
	T2 t = new T2();
	for (int i = 0; i< 10;i++)
	{
		threads.add(new Thread(()-> {t.m();}));
	}
    threads.forEach((o)->{o.start();});
    threads.forEach((o)->{try {
		o.join();
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}});
    System.out.println(t.count);
}

}

volatile的底层实现

  • 可见性-缓存一致性(TBD)
    • 防止重排序-内存屏障(JMM TBD)

一个有名的singleton的线程安全实现

package juc.volatil;

public class T1 {
   private volatile static T1 INSTANCE;
   public static T1 getInstance() {
	   if(INSTANCE == null)
	   {
		   try {
			Thread.sleep(300);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		   synchronized(T1.class) {
			   INSTANCE = new T1();	   
		   }
	   }
	   return INSTANCE;
   }
   public static void main(String[] args) {
	   for(int i = 0 ;i < 100 ;i++)
	   {   new Thread(()->{
		   
		   System.out.println(T1.getInstance().hashCode());
	   }).start();
		   
	   }
   }
}

 

你可能感兴趣的:(学习volatile)