2016-08-16 5 views
0

以下はサンプルクラスです(これは私がテストしたものです)。これはスレッドセーフなクラスかどうかを知りたいと思います。Javaのインスタンス変数とスレッドの安全性

インスタンス変数が必ずしもスレッドセーフではないと答えた他の投稿とブログを参照してください。 (ほとんどのプリミティブ型で示されている例)

メソッドの外にOutputResponseオブジェクトを作成し、それをsoapuiからロードテストすると、失敗していましたが、メソッド内でオブジェクトを作成すると常にロードテストが成功しました。

@Service 
public class ExampleProvider { 

    private OutputResponse outputResponse; 

     @Post 
     @Path("/test") 
     @Consumes("application/json") 
    @Produces("application/json") 
     public OutputResponseEntity execute (InputRequest inputRequest) { 

     outputResponse = new OutputResponse(); 
      outputResponse.setSomeValue("this is test"); 
      populateOutputResponse(); 
     } 

     private OutoutResponseEntity<OutputResponse> populateOutputResponse() { 
      if(null != inputRequest) { 
       outputResponse.setSomeOtherValue(inputRequest.getName()); 
      } 
      return new OutputResponseEntity(outputResponse,httpstatus.OK); 
     } 
} 
+0

'@ Service'とそれ以外のアノテーションにはどのようなフレームワークを使用していますか? – markspace

+1

いいえ、スレッドセーフではありません。変更可能なプライベート共有データがあります。それは「安全ではない」という定義です。プライベートデータメンバを削除し、メソッドに対してローカルのOutputResponseを作成します。スレッドセーフです。 – duffymo

+0

@duffymo私は同じことを期待していましたが、メソッド内部でOutputResponse変数をローカルに作成するのは、スレッドセーフであり、インスタンス変数として「スレッドセーフではありません」としていますが、ロードテストは常に成功します。 soapuiで2と終了スレッド数をカウントします。 – jagan

答えて

0

あなたの投稿コードが構文的に、かなり右ではないようです - あなたが何か意味した:それはあなたが何を意味するかだと仮定すると、

public OutputResponseEntity execute (InputRequest inputRequest) { 
    outputResponse = new OutputResponse(); 
    outputResponse.setSomeValue("this is test"); 
    return populateOutputResponse(inputRequest); 
} 

を複数のスレッドを使用しているように、それはそうですExampleProviderの同じインスタンス。それはなぜoutputResponseをにローカルにするのですか?そしてそれをpopulateOutputResponseにも渡すことをお勧めします)あなたのテストを修正します。

ExampleProviderの同じインスタンスを複数のスレッドが使用している場合、コードが今度はoutputResponseもスレッド間で共有されており、競合状態を防ぐために同期が行われていません。したがって、このような何かが起こる可能性:outputResponse

  • JVMコンテキストの共有インスタンスの1が完了setSomeOtherValue(...)

    • スレッドは2スレッドに切り替わり、outputResponseの同じインスタンス上setSomeValue(...)を完了します。 outputResponseにスレッド1とスレッド2の両方の状態が含まれるようになりました。
    • JVMコンテキストはスレッド1に戻り、この混合状態オブジェクトに基づいてOutputResponseEntityが作成されます。

    あなたはexecuteメソッドへoutputResponseは、ローカル作り、それを周りに渡す場合は、スレッドごとに、そのオブジェクトの別のインスタンスを持ってますので、それが効果的に、スレッドローカルメモリになります。これはおそらくあなたが望むものです。スレッド間で情報を共有する必要がない場合は、ローカル変数にしてください。スレッド間でセット/獲得を実際に行う必要がある場合(この単純な例ではそうではないようですが)、何らかの同期を行う必要があります。あなたの要望)。

  • 0

    このクラスは、設計上、スレッドセーフではありません。しかし、いくつかのフレームワークではコンポーネントとして明確に使用されています。可能であれば、このフレームワークはスレッド間でExampleProviderのインスタンスが共有されないことを保証します。そうであれば、クラスのスレッドセーフティは問題ではなく、テストの結果に影響を与えません。

    +0

    スプリングフレームワークが使用されており、私の理解によれば、それらはデフォルトでシングルトンとして作成されるため、ExampleProviderはスレッド間で共有されます – jagan

    関連する問題