一个类的对象锁只有一个,如果有几个非静态函数都是synchronized,在某一时刻只有一个线程能调用其中一个函数
假如一个类有几个静态函数是synchronized,在某一时刻只有一个线程能调用其中一个静态函数吗?也就是类锁也只有一个吗?
巴扎黑2017-04-18 10:51:00
前面一種鎖的是實例對象,鎖定了當前的那個對象,如果有多個實例對象,這些synchronized
方法之間不是同步的。第二種鎖的是類別對象,類別對象就一個,所以是同步的。
PHP中文网2017-04-18 10:51:00
public class Foo {
synchronized void test1() {
//to implements
}
void test2() {
synchronized(this) {
//to implements
}
}
synchronized static void test3() {
//to implements
}
static void test4() {
synchronized(Foo.class) {
//to implements
}
}
}
如上程式碼,test1方法相當於test2,當this是同一個物件時,就會發生阻塞。當然,不同對象沒有關係,因為this不一樣。稱為物件級鎖。
test3相當於test4,這裡是用class物件當鎖,因為一般情況下一個類別的類別實例只有一個,那麼每次進入這個方法都會鎖。稱為類級鎖。
大家讲道理2017-04-18 10:51:00
非靜態同步方法(A)用的鎖就是當前實例物件本身,一個實例的A獲取鎖定之後,該實例的其他A必須等待鎖的釋放,多個實例用的都是不同的鎖;
靜態同步方法(B)用的鎖是類別物件本身,一旦一個B取得鎖之後其他的B都必須等待釋放鎖,不管是一個實例還是多個實例;
另外 A和B之間用不同的鎖,所以不會有競爭關係;
伊谢尔伦2017-04-18 10:51:00
你說的是「互斥鎖」的概念,針對synchronized修飾法有兩種情況:
【非靜態方法】
當一個方法被synchronized修飾後,鎖定對象為目前方法所屬對象,即方法中的this。
【靜態方法】
當一個靜態方法被synchronized修飾後,此靜態方法上鎖的物件為目前類別物件(Class類別的實例)。每個類別都有唯一的一個類別物件。取得類別物件的方式:類別名稱.class。
而對於互斥的場景,需要理解兩點說明:
1、靜態方法與非靜態方法同時聲明了synchronized,他們之間是非互斥關係的。原因在於,靜態方法鎖的是類別物件而非靜態方法鎖的是目前方法所屬物件。
2、當Synchronized修飾的是兩段不同的程式碼,但是鎖定物件相同時,兩個執行緒分別呼叫者兩段程式碼時就是互斥的
所以你說的「一時刻只有一個執行緒能呼叫其中一個函數」(即互斥),判斷條件就是鎖物件是否相同,與方法型別無關。
伊谢尔伦2017-04-18 10:51:00
物件方法的synchronized修飾,鎖為物件自身,也就是this;
靜態方法的synchronized修飾,鎖為Class物件自身,也就是由類別載入器建立的類別物件;