1

私は次のようなことをよくしています。スレッドに送信するオブジェクトのコピーを作成します。オブジェクトを使用するのはスレッドだけであり、事前発生の関係があるため、スレッドセーフです。

しかし、これは私緊張させます。コメントにあるように、誰かがやってきて objForThread をいじったらどうなるでしょうか? ロックを使用する必要がありますか? それとも、これは一般的に受け入れられている Java パターンですか?

class Example
{
  private SomeObj mDynamicObj = new SomeObj();

  public void doWorkInAThread()
  {
    mutateThis(mDynamicObj);
    final SomeObj objForThread = new SomeObj(mDynamicObj);

    myExecutorService.submit(new Runnable() { @Override public void run()
    {
      doSomethingWith(objForThread);
    }});

    mutateThis(mDynamicObj);

    // Concerned that in the future someone will come
    // along and mutate objForThread here making this thread unsafe
  }
}
4

3 に答える 3

1

緊張している場合は、ローカルに保持せずにスレッドへの参照を渡すことをお勧めします。

class Example
{
    private SomeObj mDynamicObj = new SomeObj ();

    public void doWorkInAThread ()
    {
        class MyRunnable implements Runnable
        {
            private final SomeObj objForThread;

            public MyRunnable (SomeObj objForThread)
            {
                this.objForThread = objForThread;
            }

            @Override
            public void run ()
            {
                doSomethingWith (objForThread);
            }
        }

        mutateThis (mDynamicObj);

        myExecutorService.submit (new MyRunnable (new SomeObj (mDynamicObj)));

        mutateThis (mDynamicObj);
    }
}
于 2013-02-08T23:03:35.397 に答える
0

コードを壊す可能性のある変更を行う人からコードを守ることは困難です。

それはあなたの問題ではないと主張することができます。警告コメントを追加して先に進むことができます。または、次の人は賢く、彼の変更の意味を理解するのに十分注意深いと仮定することもできます。

または、SomeObj をスレッドセーフまたは不変に変更するなどの防御的な手順を実行することもできますが、これにより実行時のオーバーヘッドが追加される可能性があります。

どのアプローチが最適ですか? それについてはアドバイスできないと思います。それはより高いレベルの問題に依存します。たとえば、チームとそのコード レビューおよびテスト手順がどれほど優れているか、アプリケーション全体がどれほど複雑か、パフォーマンスがどれほど重要か、エラーがどれほど重要かなどです。


この特定の「例」では、アプリケーション ロジックに似たものはすべて抽象化されているため、どのアプローチが最適かを判断するのが難しくなっています。ローカル オブジェクトを渡すことが「良い」か「悪い」かは、コンテキストによって異なります。

于 2013-02-09T02:51:03.280 に答える
0

それはすべて、達成しようとしていることに依存します。一部のデータは、複数のスレッドによってアクセスおよび変更されるように設計されています。一部のデータは、スレッド セーフ環境でのみ使用するように設計されています。

より詳細な説明が必要な場合は、実際の例を提供する必要があります。

さらに、一部のクラスは、スレッド セーフまたは不変になるように設計されています。たとえば、String または Integer を共有することはまったく問題ありません。ただし、これらのオブジェクトへの実際の参照は変更される可能性があるため、そのような参照に依存すると問題が発生する可能性があります。

あなたの例では、最終変数を介してオブジェクトを参照するため、後者は当てはまりません。ただし、メンバー変数 mDynamicObject を参照する場合、別のスレッドの誰かが別のオブジェクトを割り当てた場合 (mDynamicObject = new SomeObj()) に問題が発生します。適切な同期がないと、アプリケーションが奇妙な状態になる可能性があります。それを回避するには、それを最終変数に割り当てて参照することができます。

パラメータを参照する代わりに、できるだけ多くのパラメータを新しいスレッドの呼び出しに渡すことを検討してください。これにより、参照先が変更されないことが保証されます。

そしてもちろん、必要に応じてオブジェクト自体を不変にするか、適切に同期することをお勧めします。

于 2013-02-08T22:59:30.757 に答える