使用同步的原因
1. 在系統中對訪類別要使用多執行緒進行存取;
2. 在該類別中有類別變量, 或是在類別的方法中有存取公共資源(如一個外部文件的讀寫)。
同步鎖定鎖定的內容是什麼?
無論你將Synchronized加在方法前還是加在一個變數前,其鎖定的都是一個 類別物件。每一個物件都只有一個鎖與之相關聯。
下例中分情況的列舉各種情況下的同步效果
1. Synchronized 加在方法上, (同步方法,鎖定類別實例)
Java程式碼
public class Demo1 { public synchronized void m1(){ //............... } public void m2(){ //............ synchronized(this){ //......... } //........ } }
這兩種寫法的效果是一樣的,鎖定的都是類別實例物件。如果有一個類別實例物件: demo = new Demo1(),另外有兩個線程: thread1,thread2,都調用了demo 對象,那麼,在同一時間,如果thread1調用了demo.m1(),則thread2在該時間內不能存取demo.m1() 和demo.m2(); 因為thread1把demo這個物件的鎖定使用了,所以無法分給其它執行緒使用
但是,如果thread1呼叫demo1.m1() , thread2呼叫demo2.m1(), 則可以同時進行,因為它們呼叫的是不同的Demo1類別物件實例。
2. Synchronized 加在變數上, (同步區塊,鎖定類別實例)
Java程式碼
public class Demo2 { Object a = new Object(); Object b = new Object(); public void m1(){ //............ synchronized(a){ //......... } //........ } public void m2(){ //............ synchronized(b){ //......... } //........ } }
在這種情況下,是實現程式碼區塊鎖定,鎖定的物件是變數a 或b; (注意,a 、b 都是非static 的)如果有一個類別實例物件: demo = new Demo2(),另外有兩個執行緒:thread1,thread2,都調用了demo 對象,那麼,在同一時間,如果thread1調用了demo.m1(),則thread2在該時間內可以訪問demo.m2();但不能訪問demo.m1() 的同步塊,因為a被thread1鎖定了。
3. Synchronized 鎖定的是類別變量,即static 變數(可能是屬性,可能是方法)(鎖定類別物件)
Java程式碼
public class Demo3 { static Object o = new Object(); public static synchronized void m1() { //.... } public static void m2() { //... synchronized (Demo3.class) { //..... } //..... } public static void m3() { //.......... try { synchronized (Class.forName("Demo3")) { //............ } } catch (ClassNotFoundException ex) { } //............. } public static void m4() { //............ synchronized(o){ //........ } //.......... } }
public class Demo4 { static String path = "file path"; public void readConfiFile() { synchronized (path) { // 读取该path指定的文件。 } } public void writeConfiFile() { synchronized (path) { //写信息到该path指定的文件。 } } }
以上是Java如何利用Synchronized實現多執行緒同步的詳細內容。更多資訊請關注PHP中文網其他相關文章!