5

以下のスニペットのような(本番!)コードに遭遇しました:

synchronized(some_object) {
    some_object = new some_object()
}

これはあらゆる種類の恐ろしい競合状態の影響を受けると予想され、新しいオブジェクトが作成されると、2番目のスレッドがこのブロックに入る可能性があります。私のJavaチョップは、上記の予想される動作を明確に述べるのに十分ではないので、これをリファクタリングする前に、皆さんが何を言わなければならないのか興味があります。

4

4 に答える 4

4

何が起こっているかによっては、これは実際には問題ない可能性があります。より大きな文脈を理解する必要があります。some_object同期は、ブロックの先頭でが指しているオブジェクトで行われます。説明から、それがバグであることを確認するのに十分な情報がありません。

同期自体は問題なく機能します。

于 2012-05-24T23:09:58.493 に答える
2

フランシスが言うように、これは問題ではないかもしれません。スニペットはこれと同等です:

SomeObject saved = some_object;
synchronized(saved) {
  some_object = new SomeObject()
}
于 2012-05-24T23:12:53.130 に答える
1

同期は、同期ブロックに入るときに参照されたオブジェクトで行われます。同期されたブロック内の別のオブジェクトへの参照をポイントしても、同期にはまったく影響しません。それはまだ「古い」オブジェクト上で同期されています。

于 2012-05-24T23:22:42.517 に答える
1

これはかなり悪いです。同期は、最終クラスのメンバーに最適です。

スレッドセーフな方法でオブジェクトを作成するための最新のアプローチは、GoetzのJava Concurrency in Action(第15章)で説明されているように、ループでAtomicReferencecompareAndSetを使用することです。これはスレッドをブロックせず、同期ブロックよりもはるかに優れたパフォーマンスを提供します。

private final AtomicReference<SomeObject> someObject = new AtomicReference<>();


void buildIt() {
   SomeObject obj = new SomeObject();
   SomeObject current = someObject.get();  //probably null, but doesn't matter
   while (true) {
      if (someObject.compareAndSet(current, obj)) 
          break;
   }
}
于 2012-05-25T00:11:24.130 に答える