2012-06-29 120 views
0

您好我有多種方法,我需要synchronized塊在所有的方法是這樣一類:同步塊問題?

public class Test2 { 
    private Object mutex=new Object(); 
    private OtherClass obj=new OtherClass(); 

    public void method1(){ 
     //do some stuff 
     synchronized (mutex) { 
      obj.//some method 
      //do some stuff 
     } 
     //do other stuff 
    } 

    public void method2(){ 
     //do some stuff 
     synchronized (mutex) { 
      obj.//some method 
      //do some stuff 
     } 
     //do other stuff 
    } 

    public void method3(){ 
     //do some stuff 
     synchronized (mutex) { 
      obj.//some method 
      //do some stuff 
     } 
     //do other stuff 
    } 

    public void method4(){ 
     //do some stuff 
     synchronized (mutex) { 

      obj.//some method 
      //do some stuff 
     } 
     //do other stuff 
    } 
} 

我使用互斥塊同步,所以會發生什麼,如果正在使用method1時,其他method2同步塊等待,直到流出同步塊method1

我不希望發生這種情況,所以我該怎麼辦?我知道,因爲我正在爲所有方法使用互斥鎖,所以它鎖定了method2同步塊。我想知道我該怎麼做才能刪除它?我應該爲每種方法創建成員變量嗎?還是有其他解決方法?

我希望其他線程只有在調用相同的方法時纔會等待。就像兩個線程對mehod1進行分類,因此第二個線程應該等待。但如果第二個線程調用method2,它不應該等待。

+0

如果這不是你想要的行爲,你想什麼'method2'去做?跳過塊?然後同步不是你正在尋找... – brimborium

+0

我想其他線程只有等待,如果調用相同的方法..喜歡如果兩個線程類mehod1所以第二個線程應該等待。但如果第二個線程調用method2,它不應該等待。 – Harinder

+0

向下投票 - 非常本地化的問題,即使作者在問題中提出這個問題,答案也非常明顯。 – Romain

回答

4

根據您的評論來判斷我假設您想要按方法同步而不是按對象。在這種情況下,最簡單的方法是爲每個方法聲明一個單獨的監視器對象,即mutex1,mutex2等。

+0

所以你的意思是說,如果我有大約20種方法?我應該有20個互斥體對象?沒有其他解決方法嗎? – Harinder

+0

那麼你可以聲明一個包含20個對象的數組,比如'Object [] mutexes = new Object [20];'併爲每個方法使用不同的索引,所以你不需要聲明20個類成員。 – Tudor

+0

@ Dennis:由於每個線程都有自己的私有堆棧,因此在本地聲明它們會使每個線程看到不同的互斥鎖,這將是無用的。他們需要全球可見。 – Tudor

4

您應該在method2方法中使用另一個mutext。

+0

所以你的意思是說,如果我有大約20種方法?我應該有20個互斥體對象?沒有其他解決方法嗎? – Harinder

2

只需在每種方法中使用不同的監視器。

public class Test2 { 
    private Object mutex1 = new Object(), mutex2 = new Object(); 
    private OtherClass obj=new OtherClass(); 

    public void method1() { 
     //do some stuff 
     synchronized (mutex1) { 
      obj.//some method 
      //do some stuff 
     } 
     //do other stuff 
    } 

    public void method2() { 
     //do some stuff 
     synchronized (mutex2) { 
      obj.//some method 
      //do some stuff 
     } 
     //do other stuff 
    } 
} 

如果你有很多方法,你也可以將它們打包在一個數組中。

+0

這些也可以是局部變量或他們不會工作?他們必須是成員變量? – Harinder

+1

@Dennis局部變量不會工作,因爲每個方法的調用都有自己的局部變量。 –

+1

@ Dennis它們不能是局部變量,因爲在每次方法調用時都會創建新變量。同步不會那樣工作... – brimborium

2

如果您想實現這個目標並對它們進行同步,您必須爲每個方法調用使用不同的監視器對象(代碼中的mutex)。如果你有很多方法,你可以使用一些集合類握住你的互斥對象:

public class Test2 { 
    private Object[] mutexes=new Object[2]; 
    private OtherClass obj=new OtherClass(); 

    private synchronized Object getMutex(int i) { 
     if(mutexes[i] == null) { 
      mutexes[i] = new Object(); 
     } 
     return mutexes[i]; 
    } 

    public void method1(){ 
     //do some stuff 
     synchronized (getMutex(1)) { 
      //do some stuff 
     } 
     //do other stuff 
    } 

    public void method2(){ 
     //do some stuff 
     synchronized (getMutex(2)) { 
      //do some stuff 
     } 
     //do other stuff 
    } 
} 

請注意,如果您同步在每個方法的基礎,但每種方法從訪問同一個對象(obj你的情況)​​塊,對該特定對象的訪問仍然不是線程安全的。

的另一個選項是初始化在構造函數中的所有互斥鎖代替點播在getMutex()方法創建它們的:

public Test() { 
    for(int i = 0; i < mutexes.length()) { 
     mutexes[i] = new Object(); 
    } 
} 
+0

您需要**'getMutex(int)'方法是'synchronized'(或對'mutexes'使用同步的雙重檢查),或者兩個調用可以獲得兩個不同的互斥鎖。 (A檢查,A分配互斥體,B其他檢查,A分配互斥體,B分配互斥體,KABOOOM)。 – Romain

+0

@Romain:你說得對,我已經更新了這個例子。另一個選擇是在方法調用之前初始化所有的互斥體(例如在'Test2'構造函數中),然後根本不需要'null'檢查。 – buc

+0

是的。像private private Object [] mutexes = {new Object(),new Object()};'會很好地完成這項工作。 – Romain