[英]static members when used in synchronized method or block in java
當我在實例方法上使用synchronized方法時,監視器與'this'相關聯。 另一方面,當我在我的類(靜態)方法上進行同步時,監視器與類對象相關聯。 當我在非靜態方法中使用靜態變量時會發生什么? 會同步嗎?
例如,
public class A{
public static int reg_no = 100;
public synchronized void registration(){
A.reg_no = some operation...
}
}
在上面的例子中,如果兩個或多個線程競爭方法registration()
,靜態變量reg_no
會發生什么?
使用synchronized
注釋成員函數時,該方法將在對象的實例上同步。 如果要在靜態變量上進行同步,則必須手動同步類對象 :
public synchronized void registration() {
synchronized (A.class) {
A.reg_no = some operation ...
}
}
請注意,上面獲得了兩個鎖,如果任何其他代碼在另一個順序中獲得相同的兩個鎖,則可能導致死鎖 。 您可能希望從方法中刪除synchronized
,只保留synchronized (A.class)
。
對變量(靜態或實例)的訪問不同步。 該方法的同步將防止單個實例的競爭條件,無論變量(靜態或實例)如何
如果你想要防范多個實例,你必須在類文字上進行同步,但這看起來確實是錯誤的。
(經過進一步思考后修改)
對於上面給出的示例,您可以通過聲明您的靜態int像punkers建議的那樣揮發。
但是在一般情況下 - 例如,如果你的靜態變量是一個具有可變狀態的對象......
synchronized實例方法意味着只允許持有對象實例鎖的線程在該類A實例的該方法中進行,並且當該線程在該方法中完成並釋放鎖時,任何其他線程使用任何其他線程進入任何同步塊相同的鎖將“看到”您所做的更改。
它不會阻止被改變到另一個線程其靜態變量做:
使用synchronized方法通常有點危險 - 它們可能導致死鎖,因為鎖可以由其他使用您的類/實例作為同步塊的目標的代碼從外部獲取:
synchronized (objectOfTypeA) { ... } // takes the instance lock
要么
synchronized (A.getClass()) { ... } // takes the class lock
更好的方法可能是將靜態變量設為私有,添加私有本地變量以用作鎖(因此無法在外部鎖定),並在方法中的synchronized塊中使用私有本地鎖:
public class A {
private static int reg_no = 100;
private static Object lock = new Object();
public void registration(){
synchronized(lock) {
reg_no = some operation...
}
}
public static int getRegNo() {
synchronized(lock) {
return reg_no;
}
}
}
不,您需要將方法與類同步,例如。 synchronized(A.class)
。
如果您的問題是與其他線程共享該變量,我會將靜態變量聲明為volatile,而不是在同步方法中添加另一個同步塊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.