2012-03-14 25 views
2

我的Java代碼如下所示:方法上一個更新的領域同步

class xHandler 
{ 
    private Channel _channel; 

    // Methods... 

    void init() 
    { 
     _channel = new Channel(...); 

     synchronized (_channel) 
     { 
      // Do some stuff here...e.g. 
      _channel.send("..."); 
     } 
    } 
} 

在其他文件(線程)創建頻道的情況,並參照使用對象的送東西,但只在init方法上面提到我需要它同步,並沒有其他線程應該打開一個頻道,並在此期間發送的東西。

FindBugs的給了我一個名爲警告:方法上同步更新的領域

這種方法同步從一個可變字段引用的對象上。 這不太可能有用的語義,因爲不同的線程可能在不同的對象上進行同步。

我該如何解決這個問題?用簡單的測試可以輕鬆觸發這個問題嗎?

+4

你的代碼是無效的 - 你不能你'init'方法中聲明場......沒有你的意思是要一個簡單的任務? – 2012-03-14 14:06:21

+0

可變字段意味着專用Channel _channel不是最終的。嘗試設置場地決賽; – darijan 2012-03-14 14:07:22

+0

Thx喬恩Skeet的提示,我編輯,現在應該是正確的。 – arge 2012-03-14 14:23:07

回答

1
_channel = new Channel(...); 
synchronized (_channel) 

我需要它來sync'ed並沒有其他線程應該打開一個通道和 在此期間送東西。

看起來像你的代碼沒有做你認爲它在做什麼。由於您正在爲每個xHandler實例創建一個新的對象,並獲取此特定的鎖,因此可以同時運行兩個線程。

  1. xHandler實例1創建Channel實例1和獲取它的鎖
  2. xHandler實例2創建通道實例2,取得
  3. 兩種運行它的鎖同時

你真正需要做的是什麼其中之一:

  1. 分享您要爲mu同步的特定Channel對象(例如:在xHandler構造函數上接收Channel的實例並將其分配給_channel,刪除_channel = new Channel(...);行並保持同步代碼原樣)。
  2. Channel.class上同步,這意味着兩個不同的xHandler實例將永遠不能同時使用任何Channel。共享特定Channel兩個不同xHandlers

例子:

class xHandler 
{ 
    private final Channel _channel; 

    public xHandler(Channel channel) 
    { 
     this._channel = channel 
    } 

    // Methods... 

    void init() 
    {   
     synchronized (_channel) 
     { 
      // Do some stuff here...e.g. 
      _channel.send("..."); 
     } 
    } 

      public static void main(String[] args) 
      { 
       Channel myChannel = new Channel(...); 
       xHandler xHand1 = new xHandler(myChannel); 
       xHandler xHand2 = new xHandler(myChannel); 
       // Code to create/start your threads. 
       // xHand1 and xHand2 will not use myChannel simultaneously 
      } 

} 
3

請注意​​正在獲取鎖定對象而不是變量!

此方法的每個調用都會鎖定不同的對象,因此在此處的同步塊實際上是多餘的,因爲您在輸入init()時修改它。 [如警告所示,不同的線程正在不同的對象上同步]。

如果兩個線程同時嘗試調用init()會發生什麼?他們兩人都可能同時進入關鍵部分,這就是你所警告的。

要解決這個問題,您可能需要聲明_cahnnelfinal,並在構造函數中初始化它,而不是在init()中初始化它。

2

每次運行該方法時都會繼續創建新的鎖。因此你正在否定鎖定的影響。該鎖將始終允許新線程進入,因爲沒有線程正在等待新創建的對象(現在可能會通過某些race condition)。每個線程基本上都有自己的鎖(而不是共享鎖)。

移動channel以外的方法。