synchronizedjava
同步塊你們都比較熟悉,經過 synchronized 關鍵字來實現,全部加上synchronized 和 塊語句,在多線程訪問的時候,同一時刻只能有一個線程可以用 synchronized 修飾方法或者代碼塊。多線程
volatile線程
用volatile修飾的變量,線程在每次使用變量的時候,都會讀取變量修改後的值。volatile很容易被誤用,用來進行原子性操做。blog
如下兩段程序演示了二者區別內存
package net.dp.volatileTest; public class JoinThread extends Thread { public static volatile int n = 0; public void run() { for (int i = 0; i < 10; i++) try { n = n + 1; sleep(3); // 爲了使運行結果更隨機,延遲3毫秒 } catch (Exception e) { } } public static void main(String[] args) throws Exception { Thread threads[] = new Thread[100]; for (int i = 0; i < threads.length; i++) // 創建100個線程 threads[i] = new JoinThread(); for (int i = 0; i < threads.length; i++) // 運行剛纔創建的100個線程 threads[i].start(); for (int i = 0; i < threads.length; i++) // 100個線程都執行完後繼續 threads[i].join(); System.out.println(" n= " + JoinThread.n); //執行結果 n < 1000 } }
程序的運行結果是n小於1000.同步
緣由:Java在建立線程的時候會爲每個線程分配線程當前的內存空間用來存放當前線程中的變量,存儲在棧中;這些變量最終的值是存儲在堆中。也就是說棧中會有堆中變量值的副本。volatile關鍵字是保證不一樣線程對該變量的訪問是從堆中獲取,拿到的是同一個變量的真實值不是棧中的副本。可是這並不能保證該操做是原子性的。在程序中n = n + 1操做就不是原子性的因此纔會出錯。io
使用synchronized關鍵字解決該問題。class
package net.dp.volatileTest; public class JoinThread2 extends Thread { public static int n = 0; public static synchronized void inc() { n++; } public void run() { for (int i = 0; i < 10; i++) try { inc(); // n = n + 1 改爲了 inc(); sleep(3); // 爲了使運行結果更隨機,延遲3毫秒 } catch (Exception e) { } } public static void main(String[] args) throws Exception { Thread threads[] = new Thread[100]; for (int i = 0; i < threads.length; i++) // 創建100個線程 threads[i] = new JoinThread2(); for (int i = 0; i < threads.length; i++) // 運行剛纔創建的100個線程 threads[i].start(); for (int i = 0; i < threads.length; i++) // 100個線程都執行完後繼續 threads[i].join(); System.out.println(" n= " + JoinThread2.n); } }
程序執行結果是1000 thread
使用synchronized關鍵字對自增操做修飾,保證了自增的原子操做。變量