非常に複雑なコードを少し変更しているので、これに独自の同期を追加する必要があります。
ただし、既存のコードには、それ以上ではないにしても、約12の異なるロックがあり、私のコードはそのメソッドのいくつかを呼び出す必要があります。ロックが取得される順序はよくわかりません。また、実際に制御することもできません。
だから、私の質問は、すべての異なるロックを単一のロックに置き換えたらどうなるでしょうか?粒度を犠牲にする以外に、私が知っておくべき他の問題はありますか?
ありがとう!
非常に複雑なコードを少し変更しているので、これに独自の同期を追加する必要があります。
ただし、既存のコードには、それ以上ではないにしても、約12の異なるロックがあり、私のコードはそのメソッドのいくつかを呼び出す必要があります。ロックが取得される順序はよくわかりません。また、実際に制御することもできません。
だから、私の質問は、すべての異なるロックを単一のロックに置き換えたらどうなるでしょうか?粒度を犠牲にする以外に、私が知っておくべき他の問題はありますか?
ありがとう!
すべてのsynchronized
ブロック (およびメソッド)と他のすべてのブロック構造を変更しても問題ないと思います。最悪の場合、アプリはシリアル実行に劣化します。しかし、それらの一部だけを変更すると、デッドロックが発生する可能性があります。2 つのスレッドがそれぞれ複数のロックを取得しているシナリオを考えてみましょう。
Thread 1:
synchronized A
synchronized B
Thread 2:
synchronized B
synchronized C
ここでデッドロックのリスクはありませんが、A
and C
(ただし ではないB
) を新しい一般的なロックに置き換えると、次のようになります。
Thread 1:
synchronized L
synchronized B
Thread 2:
synchronized B
synchronized L
...これは古典的な行き詰まりのケースです。
ロック自体がデッドロックを提供するのではなく、代わりに CountDownLatch のようなブロッキング クラスをデッドロックする別のシナリオを考えてみましょう。
Thread 1:
synchronized A
latch L.countDown()
Thread 2:
synchronized B
latch L.await()
この場合、両方のsynchronized
ブロックを共通のロックでロックするように変更しても、それらの間でデッドロックは発生しませんが、スレッド 2 が最初にロックを取得するとデッドロックが発生します。スレッド 1 がブロックされているため、ラッチの countDown が発生するのを待ちます。そのsynchronized
エントリーポイントで。この例は、セマフォ、ブロッキング キューなど、他のブロッキング構造にも適用されます。
コードを適切に分析することに代わるものはないと思います。それがひどい理由はおそらく、それを変更しなければならなかった他のすべての人があなたとまったく同じことをし、適切な分析に失敗したためです.
ロックを明確にするロギング コードを作成するのはかなり簡単です。レイヤーの選択を解除して明確な画像が得られたら、全体を などの最新のロックに置き換えるのは比較的簡単ReadWriteLock
です。
この機会にテスト コードを追加して、制御された方法でログ記録を実行すると便利な場合があります。複雑なコードに追加するのに非常に便利です。
コードを見ずに何が起こるかを正確に言うのは難しい。ロックの1つにいるときに、別のロックを取得しようとすると、デッドロックの問題が発生する可能性があります。また、単一のロックと複数のロックの取得を待機している間、アプリケーションの速度が低下する可能性があります。