java - synchronized關鍵字
阿新 • • 發佈:2021-01-11
synchronized使用總結
java多執行緒同步處理經常會使用到synchronized關鍵字,之前對其使用場景有些模糊不清,故做一些整理。
一、使用synchronized修飾非靜態方法
1 public class Hello{ 2 3 public synchronized void sayHello(){ 4 System.out.println("Hello world"); 5 } 6 }
這種方式是對每一個Hello物件上鎖,第一個訪問該方法的執行緒A則持有當前Hello物件的鎖,執行緒B要訪問該物件的執行緒會被阻塞,直到執行緒A訪問結束釋放該物件的鎖執行緒B才能訪問。但是如果執行緒B訪問的是Hello的另外一個物件,則不會被阻塞,因為sayHello是一個非靜態方法。
二、使用synchronized修飾靜態方法
1 public class Hello{ 2 3 public synchronized static void sayHello(){ 4 System.out.println("Hello world"); 5 } 6 }
static關鍵字修飾的方法表示該方法是一個類方法,與類的物件無關,所以當執行緒A首先持有了sayHello的鎖後,執行緒B無論訪問Hello的那個物件都會阻塞。
三、使用synchronized同步塊
前面兩種方法雖然能實現同步,但是效率不是很高。假設Hello有兩個被synchronized修飾的方法。當執行緒A訪問sayHello()時會持有Hello物件的鎖,這時,如果執行緒B
去訪問sayBye()時會被阻塞,因為訪問syaBye()需要持有Hello物件的鎖。有時候可能sayHello()和syaBye()併發不會有影響,這樣做就會降低程式效率。
public class Hello { public synchronized void sayHello() { System.out.println("Hello world"); } public synchronized void sayBye() { System.out.println("bye bye"); } }
所以java有了synchronized同步塊的使用,同步塊也可以分為兩種。靜態和非靜態。
非靜態同步塊:
public class Hello { private final Object lockHello = new Object(); private final Object lockBye = new Object(); public void sayHello(){ synchronized (lockHello) { System.out.println("hello"); } } public synchronized void sayBye() { synchronized (lockBye) { System.out.println("bye"); } } }
這樣當執行緒A訪問sayHello時就不會影響執行緒B訪問sayBye了。靜態和非靜態的區別與前面兩種是一樣的。
靜態同步塊:
public class Hello { private static final Object lock = new Object(); public void sayHello(){ synchronized (lock) { System.out.println("hello"); } } }