volatile關鍵字要求線程在使用變量的時候,必須立刻從主內存讀取,在修改完成以後,立刻將數據寫入主內存。
這個過程沒法對線程進行同步。
好比:
線程1從主內存讀取到count的值爲2,尚未操做的時候,線程2從主內存也把count讀取到線程內部,這個時候依然是2.
而後線程1把count自加1設爲3,當即刷新到主內存裏面。線程2也把counter自加1設置爲3,刷新到主內存裏面
這樣,線程2的操做就丟失了。
java
所以能夠使用加鎖或者AtomicInteger關鍵字來處理ide
public class VolatileWrong { volatile static int count = 0; public static void main(String[] args) { new VolatileWrong().new ThreadHandler().start(); new VolatileWrong().new ThreadHandler().start(); new VolatileWrong().new ThreadHandler().start(); new VolatileWrong().new ThreadHandler().start(); try { Thread.sleep(6000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(count); } class ThreadHandler extends Thread { @Override public void run() { for(int i = 0; i< 10000; i++){ count++; } } } }
===============================================this
import java.util.concurrent.CountDownLatch; public class VolatileWrong1 { volatile static int count = 0; public static void main(String[] args) { CountDownLatch cdl = new CountDownLatch(4); new VolatileWrong1().new ThreadHandler(cdl).start(); new VolatileWrong1().new ThreadHandler(cdl).start(); new VolatileWrong1().new ThreadHandler(cdl).start(); new VolatileWrong1().new ThreadHandler(cdl).start(); try { cdl.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(count); } class ThreadHandler extends Thread { CountDownLatch cdl ; ThreadHandler(CountDownLatch cdl){ this.cdl = cdl; } @Override public void run() { for(int i = 0; i< 1000000; i++){ count++; } cdl.countDown(); } } }
==============應使用以下代碼==========================atom
import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; public class VolatileWrong2 { static AtomicInteger count = new AtomicInteger(0) ; public static void main(String[] args) { CountDownLatch cdl = new CountDownLatch(4); new VolatileWrong2().new ThreadHandler(cdl).start(); new VolatileWrong2().new ThreadHandler(cdl).start(); new VolatileWrong2().new ThreadHandler(cdl).start(); new VolatileWrong2().new ThreadHandler(cdl).start(); try { cdl.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(count); } class ThreadHandler extends Thread { CountDownLatch cdl ; ThreadHandler(CountDownLatch cdl){ this.cdl = cdl; } @Override public void run() { for(int i = 0; i< 1000000; i++){ count.incrementAndGet(); //count.getAndIncrement(); } cdl.countDown(); } } }