第一部分: synchronized 與static synchronized 的區別java
第二部分:java多線程鎖,源碼剖析設計模式
一、synchronized與static synchronized 的區別
synchronized是對類的當前實例進行加鎖,防止其餘線程同時訪問該類的該實例的全部synchronized塊。
static synchronized是限制線程同時訪問jvm中該類的全部實例同時訪問對應的代碼塊。且一個類的全部靜態方法公用一把鎖。
以下:
pulbic class Something(){
public synchronized void isSyncA(){}
public synchronized void isSyncB(){}
public static synchronized void cSyncA(){}
public static synchronized void cSyncB(){}
}
註解:該列子來自一個日本做者-結成浩的《java多線程設計模式》多線程
那麼,假若有Something類的兩個實例a與b,那麼下列組方法何以被1個以上線程同時訪問呢異步
a. x.isSyncA()與x.isSyncB() jvm
b. x.isSyncA()與y.isSyncA()函數
c. x.cSyncA()與y.cSyncB()this
d. x.isSyncA()與Something.cSyncA()spa
這裏,很清楚的能夠判斷:線程
a,都是對同一個實例的synchronized域訪問,所以不能被同時訪問設計
b,是針對不一樣實例的,所以能夠同時被訪問
c,由於是staticsynchronized,因此不一樣實例之間仍然會被限制,至關於Something.isSyncA()與 Something.isSyncB()了,所以不能被同時訪問。
那麼,第d呢?,書上的 答案是能夠被同時訪問的,答案理由是synchronzied的是實例方法與synchronzied的類方法因爲鎖定(lock)不一樣的緣由。
我的分析也就是synchronized 與static synchronized 至關於兩幫派,各自管各自,相互之間就無約束了,能夠被同時訪問。 後面一部分將詳細分析 synchronzied 是怎麼樣實現的 。
結論 :
A: synchronized static是某個類的範圍,synchronized static cSync{}防止多個線程同時訪問這個類中的synchronized static 方法。它能夠對類的全部對象實例起做用。
B: synchronized 是某實例的範圍,synchronized isSync(){}防止多個線程同時訪問這個實例中的synchronized 方法。
二、synchronized方法與synchronized代碼快的區別 synchronizedmethods(){}與 synchronized(this){}之間沒有什麼區別,只是 synchronized methods(){} 便於閱讀理解,而 synchronized ( this){}能夠更精確的控制衝突限制訪問區域,有時候表現更高效率。
3 、synchronized
關鍵字是不能繼承的
也就是說,基類的方法synchronized f(){} 在繼承類中並不自動是synchronized f(){},而是變成了f(){}。繼承類須要你顯式的指定它的某個方法爲synchronized方法;
四、從源代碼詳細理解synchronized關鍵字(參考Observable類源碼)
Java中的Observer模式,看了其中的Observable類的源碼,發現裏面幾乎全部的方法都用了synchronized關鍵字(不是所有),其中個別用了synchronized(this){}的區塊
第二部分:Java多線程鎖,源代碼剖析
多線程的同步依靠的是鎖機制,java中可經過 synchronized 關鍵字鎖鎖住共享資源以實現異步多線程的達到同步。總結起來,要達到同步,咱們要作的就是構造各線程間的 共享資源 ,其中的共享資源能夠 對象 ,也能夠是 方法 。
package algorithms.com.guan.zoo.stackTest; public class LockDemo { public static void main(String[] args) { MyRunnerVarLock runnerVarLock = new MyRunnerVarLock(new Integer(0)); MyRunnerFuncLock runnerFuncLock = new MyRunnerFuncLock(); MyRunnerNoLock runnerNoLock = new MyRunnerNoLock(); // 對共享對象進行加鎖,線程會依次打印0-99的數,每一次運行的結果都同樣 for(int i = 0; i < 10; i++) { Thread thread = new Thread(runnerVarLock); thread.start(); } // 對共享函數進行加鎖,線程會依次打印0-99的數,每一次運行的結果都同樣 for(int i = 0; i < 10; i++) { Thread thread = new Thread(runnerFuncLock); thread.start(); } // 未加鎖,會由於線程調用的時序不一樣而發生變化,每一次運行的結果不必定相同 for(int i = 0; i < 10; i++) { Thread thread = new Thread(runnerNoLock); thread.start(); } }} // 對共享對象進行加鎖class MyRunnerVarLock implements Runnable { private Object lock; public MyRunnerVarLock(Object lock) { this.lock = lock; } public void run() { synchronized (lock) { for (int i = 0; i < 100; i++) { System.out.println("Lock: " + i); } } }} // 對共享函數進行加鎖class MyRunnerFuncLock implements Runnable { public synchronized void run() { for (int i = 0; i < 100; i++) { System.out.println("Func lock: " + i); } }} // 沒有加鎖class MyRunnerNoLock implements Runnable { public void run() { for (int i = 0; i < 100; i++) { System.out.println("No lock: " + i); } }}