14

このコードで IllegalMonitorStateException が発生する原因は何ですか

synchronized(syncCount){
    syncCount--;
    syncCount.notify();
}

私が知る限り、実行中のスレッドには通知が呼び出されたオブジェクトのモニターが必要なので、私は少し混乱しています。私のコードは間違っていないように見えますが、どういうわけかそうです。

4

1 に答える 1

23

タイプIntegerまたは類似の?--不変Integerオブジェクトを別のものに置き換えます。したがってnotify、 とは異なるオブジェクトを呼び出していますsynchronized

あなたのコードは次のものと同等です:

Integer syncConunt = Integer.valueOf(5);
[...]
synchronized (syncCount) {
    syncCount = Integer.valueOf(syncCount.intValue() + 1);
    syncCount.notify();
}

あなた一人じゃありません。J2SE 5.0 の前でさえ、同期ブロック内で参照を割り当てたサンプル コードが本に掲載されているのを見たことがあります。一般に、ロック フィールドをマークすることをお勧めしますfinal

もう 1 つの重要な点は、コードが「所有」していないオブジェクトで同期することです。Integerオブジェクトは共有されます ( Integer.valueOf(int)-128 から 127 の間、またはそれ以上の値で呼び出された場合、まったく同じインスタンスが返されます)。これが 2 つの無関係なコードによって行われた場合、隠れた相互作用が発生します。これは、関連のないコード間でインスタンスが共有されるすべての型に適用されます。一般的な例はIntegerStringClass(静的な同期メソッドで使用される) およびThread(Sun の実装では、Threadたまたま のロックとして使用されるjoin) です。

于 2010-01-12T18:37:49.197 に答える