2009-07-01 7 views
1

:「カタログ」Javaオブジェクト構造のスレッドセーフパブリッシング?私は次のコードを持っていると仮定すると

final Catalog catalog = createCatalog(); 

for (int i = 0; i< 100; i++{ 
    new Thread(new CatalogWorker(catalog)).start(); 
} 

は、オブジェクト構造、および方法createCatalog()であり、「カタログ」オブジェクトの構造は、念頭に置いて並行処理で書かれていません。製品カタログ内のいくつかの非ファイナル、非揮発性の参照がありますが、そこでも変更可能な状態であってもよい(それがを処理する必要がありになるだろう)

私はメモリモデルを理解する方法、このコードではありませんスレッドセーフです。それを安全にする簡単な方法はありますか? (スレッドが行動に爆発する前に、この問題の一般化バージョンはに作成された共有構造のシングルスレッドの建設については本当にある)

答えて

5

いいえ、シンプル安全にする方法はありません。変更可能なデータ型の同時使用は常に難しいです。 いくつかのの状況では、Catalogの同期化された(できれば非公開のロックで)同期が行われるかもしれませんが、スレッドは実際にはの操作を実行したいことがあります。 。

変数へのすべてのアクセスを同期するだけで、Javaメモリモデルの問題の関連性が低くなります。たとえば、常に最新の値が表示されますが、大きな問題自体は依然として重大です。

Catalogでどれ不変状態はすでに問題ないはずです:「事前発生」Catalogの構築と開始される新しいスレッドの間があります。スペックのsection 17.4.5から:

コールは が起こる-前 のいずれかのアクションがスレッドを開始したスレッド上で()を開始します。あなたがいないのであれば「同期」の

(と建設の仕上げがstart()への呼び出しの前に起こるので、工事が始まったスレッドのいずれかのアクションの前に発生します。)

+0

うーん、興味深い:「効果的に不変」な状態が存在していても、すべての更新を可変状態に同期させると安全だと言っていますか? (私はこれがメンテナンスの観点から危険なモデルであることを知っています) – krosenvold

+0

一般的には安全だとは言いませんが、純粋なメモリモデルの言葉では安全です。 *アップデートだけでなくすべての*アクセスを同期する必要があることに注意してください。そうしないと、読み込み時に "古い"データが得られる可能性があります。 –

+0

である。いい答えだ ;) – krosenvold

1

は、あなたがそれを作るためにCatalogの状態を変更するすべてのメソッドを同期する必要があるスレッド安全。 (おそらくこれらのスレッドが実行されている間、実際には何を変異しないことによって)あなたが扱うと仮定すると、「非ファイナル、非揮発性の参照を[と]可変状態」

public synchronized <return type> method(<parameter list>){ 
... 
} 
+0

リベラルアプリケーションは、痛みを伴うデッドロックにつながることができます注意してください。 –

1

その後、私は、これはスレッドセーフであると信じています。 the JSR-133 FAQから一のアクションが 別の前に発生する場合

、最初は 前に順序付け及び 第二に見えることが保証されます。次のようにこの順序付けのルールは です:

  • スレッド内の各アクションは、プログラムの ために、後に来るそのスレッド にある全てのアクションの前に起こります。
  • モニターのロック解除は、同じモニターの のそれ以降のロックの前に行われます。
  • 揮発性フィールドへの書き込みは、その後のすべての読み出しの前に発生します。その同じvolatileの読み出し 。
  • スレッドの開始()の呼び出しは、開始されたスレッドの のアクションの前に発生します。
  • スレッド内のすべてのアクションは、他のスレッドが正常に実行される前に実行されます。 は、そのスレッドのjoin()から戻ります。

スレッドがcreateCatalogへの呼び出し後に開始されているので、createCatalogの結果は何の問題もなく、これらのスレッドに表示されるはずです。これは、問題を引き起こすスレッドでstart()が呼び出された後に発生するカタログオブジェクトの変更のみです。

+0

エーム、あなたの最初の仮定は本当に何か他のものに私の質問を再定義しているようですね?私は知っている*私は変更可能な状態を処理する必要がありますが、私はすべての非最終的な非揮発性のものを扱うことを避ける方法があることを望んでいた。 – krosenvold

+0

あなたは「それは処理されなければならない」と言って、あなたはその部分が処理されなければならないことを知っていたことを意味しています。次に、「この問題の一般化されたバージョンは、スレッドが実際に爆発する前に作成された共有構造のシングルスレッド構築に関するものです」というものです。これは私が答えていたものです。それらを使用して開始されています。これらのオブジェクトの構築前に他のスレッドが起動されていた場合は、問題が発生する可能性があります。 –