一、引入話題-發散思考html
二、volatile深度解析java
三、解決volatile原子性問題編程
四、volatile應用場景緩存
public class T1 { /*volatile*/ boolean running=true; public void m(){ System.out.println(Thread.currentThread().getName()+":start!"); while(running){ /*try { TimeUnit.MINUTES.sleep(2); } catch (Exception e) { e.printStackTrace(); }*/ } System.out.println(Thread.currentThread().getName()+":end!"); } public static void main(String[] args) { T1 t=new T1(); new Thread(()->t.m(),"t").start(); try { TimeUnit.SECONDS.sleep(1); } catch (Exception e) { e.printStackTrace(); } t.running=false; } } 運行結果: 無volatile: t:start! 有volatile: t:start! t:end!
int a=1; int b =3; int c=a*b;
//線程1:
context = loadContext(); //語句1
inited = true; //語句2 //線程2:
while(!inited ){ sleep() } doSomethingwithconfig(context);
一、volatile能解決原子性問題嗎?什麼是原子性呢,本不想解釋,爲了讀者可以更透徹理解,再解釋一下。併發
public class T2 { volatile int count=0; public void m(){ for(int i=0;i<1000;i++) count++; } public static void main(String[] args) { T2 t=new T2(); List<Thread> threads=new ArrayList<Thread>(); for(int i=0;i<10;i++){ threads.add(new Thread(()->t.m(),"thread-"+i)); } threads.forEach((o)->o.start()); //等待全部線程都執行完
threads.forEach((o)->o.yield()); System.out.println("count:"+t.count); } } 運行結果: count:8710 //每次都不同。
二、爲何加了volatile仍是不能獲得預期結果呢?由於它只保證了可見性,不能保證原子性。what?app
再回憶java內存模型:jvm
三、那怎麼解決呢?優化
方式一:synchronized,jvm對synchronized進行了很大的優化,因此效率也沒有想象中那麼低。spa
public class T3 { int count=0; public synchronized void m(){ for(int i=0;i<1000;i++) count++; } public static void main(String[] args) { T3 t=new T3(); List<Thread> threads=new ArrayList<Thread>(); for(int i=0;i<10;i++){ threads.add(new Thread(()->t.m(),"thread-"+i)); } threads.forEach((o)->o.start()); //等待全部線程都執行完
threads.forEach((o)->o.yield()); System.out.println("count:"+t.count); } }
方式二:ReentrantLock,跟synchronized的做用差很少。線程
public class T5 { ReentrantLock lock=new ReentrantLock(); int count=0; public void m(){ lock.lock(); for(int i=0;i<1000;i++) count++; lock.unlock(); } public static void main(String[] args) { T4 t=new T4(); List<Thread> threads=new ArrayList<Thread>(); for(int i=0;i<10;i++){ threads.add(new Thread(()->t.m(),"thread-"+i)); } threads.forEach((o)->o.start()); //等待全部線程都執行完
threads.forEach((o)->o.yield()); System.out.println("count:"+t.count); } }
public class T4 { AtomicInteger count=new AtomicInteger(0); public void m(){ for(int i=0;i<1000;i++) count.getAndIncrement(); } public static void main(String[] args) { T4 t=new T4(); List<Thread> threads=new ArrayList<Thread>(); for(int i=0;i<10;i++){ threads.add(new Thread(()->t.m(),"thread-"+i)); } threads.forEach((o)->o.start()); //等待全部線程都執行完
threads.forEach((o)->o.yield()); System.out.println("count:"+t.count); } }
volatile boolean inited = false; //線程1:
context = loadContext(); inited = true; //線程2:
while(!inited ){ sleep() } doSomethingwithconfig(context);
做者:邱勇Aaron
出處:http://www.cnblogs.com/qiuyong/
您的支持是對博主深刻思考總結的最大鼓勵。
本文版權歸做者全部,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,尊重做者的勞動成果。
參考:深刻理解JVM、馬士兵併發編程、併發編程實踐
volatile關鍵字解析:http://www.importnew.com/18126.html