多線程中存在私有堆棧中的值和公共堆棧中的值不一樣步的問題。什麼意思呢?可能線程在一個地方修改了內存中變量的值,而其它地方線程卻從私有堆棧中去讀取不一致的變量值。關鍵字volatile 的主要做用是使在多個線程上可見。也就是,強制從公共堆棧中取得變量的值,而不是從線程私有數據棧中取得變量的值。java
強制從私有堆棧中取值的方法爲JVM被設置爲-server(不設置-server也是從私有堆棧中獲取值)。安全
package chapter2; public class VolatileTest { static class RunThread extends Thread{ private boolean isRunning = true; public boolean isRunning() { return isRunning; } public void setRunning(boolean isRunning) { this.isRunning = isRunning; } @Override public void run() { super.run(); System.out.println("進入run 了"); while (isRunning) { } System.out.println("線程被中止了!"); } } public static void main(String[] args) { try { RunThread runThread = new RunThread(); runThread.start(); Thread.sleep(1000); runThread.setRunning(false); System.out.println("已經賦值爲false"); } catch (Exception e) { e.printStackTrace(); } } }
運行結果:多線程
進入run 了
已經賦值爲false
永遠不會打印線程被中止了!ide
volatile private boolean isRunning = true;//強制從公共堆棧中取得變量的值this
運行結果:atom
進入run 了
已經賦值爲false
線程被中止了!線程
package chapter2; public class VolatileThread extends Thread{ volatile public static int count; private static void addCount() { for(int i=0;i<100;i++) { count++; } System.out.println("Thread:"+currentThread().getName()+"--count:"+count); } @Override public void run() { super.run(); addCount(); } }
package chapter2; public class VolatileTest { public static void main(String[] args) { VolatileThread[] volatileThreads = new VolatileThread[100]; for (int i = 0; i < 100; i++) { volatileThreads[i] = new VolatileThread(); } for(int i=0;i<100;i++) { volatileThreads[i].start(); } } }
運行結果:3d
Thread:Thread-84--count:8683
Thread:Thread-88--count:8863
Thread:Thread-89--count:8863
Thread:Thread-87--count:8963
Thread:Thread-90--count:9063
Thread:Thread-92--count:9163
Thread:Thread-97--count:9663
Thread:Thread-96--count:9563
Thread:Thread-98--count:9763
Thread:Thread-95--count:9863
Thread:Thread-93--count:9463
Thread:Thread-94--count:9363
Thread:Thread-91--count:9263
Thread:Thread-99--count:9963
server
在多線程環境中,use和assign 是屢次出現的,但這一操做並非原子性,也就是說在read和load以後,若是主內存count變量發生修改以後,線程工做內存中的值因爲已經加載,不會產生對應的變化,也就是私有內存和公有內存的變量不一樣步,因此計算出來的結果和預期不同,也就出現了非線程安全的問題。blog
package chapter2; import java.util.concurrent.atomic.AtomicInteger; public class VolatileThread extends Thread{ private AtomicInteger count = new AtomicInteger(0); private void addCount() { for(int i=0;i<10000;i++) { System.out.println(count.incrementAndGet()); } } @Override public void run() { super.run(); addCount(); } }
package chapter2; public class VolatileTest { public static void main(String[] args) { try { VolatileThread volatileThread = new VolatileThread(); Thread t1 = new Thread(volatileThread); t1.start(); Thread t2 = new Thread(volatileThread); t2.start(); Thread t3 = new Thread(volatileThread); t3.start(); Thread t4 = new Thread(volatileThread); t4.start(); Thread t5 = new Thread(volatileThread); t5.start(); } catch (Exception e) { e.printStackTrace(); } } }
運行結果:
49990
49991
49992
49993
49994
49995
49996
49997
49998
49999
50000
成功累加到50000!