2012-03-14 9 views
2

に同期します私はsync'edする必要があり、他のスレッドは、この期間中に何かを送信し、何かを送信する必要があります。方法は、私のJavaコードは次のようになり、更新フィールド

FindBugsのは私と呼ばれる警告を与える:メソッドが更新フィールド

このメソッドは、変更可能なフィールドから参照されるオブジェクトを同期化に同期します。 異なるスレッドが異なるオブジェクト上で同期している可能性があるため、これは有用なセマンティクスを持つことはほとんどありません。

どうすればこの問題を解決できますか?簡単なテストで簡単にこの問題を引き起こすことは可能ですか?

+4

あなたのコードは無効です - あなたはあなたの 'init'メソッド内でフィールドを宣言することはできません...あなたがすることを意味しました簡単な割り当てですか? –

+0

変更可能なフィールドは、プライベートチャネル_channelが最終的でないことを意味します。フィールドを最後に設定してみてください。 – darijan

+0

ヒントのためのThx Jon Skeet、私は編集しました、今は正しいはずです。 – arge

答えて

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

私はそれがsync'edする必要があり、他のスレッドがチャネルを開けないと この期間中に何かを送信する必要があります。

あなたのコードのように思われているように思えます。 xHandlerインスタンスごとに新しいChannelオブジェクトを作成し、この特定のChannelロックを取得するので、2つのスレッドが同時に実行される可能性があります。

  1. インスタンス1は、チャネルインスタンス1を作成し、それが
  2. xHandlerインスタンス2ロックです取得すると、それはどちらもあなたが本当に行う必要がある何を同時に

をされ実行

  • ロックのチャネル・インスタンス2を作成し、取得しxHandler

    1. ムーを同期する特定のChannelオブジェクトを共有するltiple xHandlerインスタンス(例:にに割り当て、コンストラクタにChannelのインスタンスを受け取り、_channel = new Channel(...);行を削除して、同期コードをそのまま使用してください)。
    2. Channel.classで同期します。これは、xHandlerの2つの異なるインスタンスが決して同時に使用できないことを意味します。

    二つの異なるxHandlersための具体的なChannelを共有する例:

    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()と入力したときに変更するので、ここの同期ブロックは実際には冗長です。 [警告では、異なるスレッドで異なるスレッドが同期されているためです]。

    2つのスレッドが同時にinit()を呼び出そうとするとどうなりますか?両方とも同時にクリティカルセクションに入るかもしれません。これが警告されています。

    _cahnnelfinalと宣言し、init()ではなく、コンストラクタで初期化したい場合があります。

    2

    メソッドが実行されるたびに、新しいロックの作成を続けます。したがって、あなたはロックの影響を否定しています。ロックは、新しく作成されたオブジェクトを待っているスレッドが存在しないため、常に新しいスレッドを許可します。各スレッドには基本的に(共有ロックの代わりに)独自のロックがあります。

    channelをメソッド外に移動します。

    関連する問題