独自のメソッドsyncedadd()を作成する場合、ロックはどのように機能しますか?ロックは、コレクションオブジェクトではなく、Xのインスタンスで実行されますか?
ロックは、同期したオブジェクトで実行されます。オブジェクト内のフィールドでは実行されません。ロックが機能するには、すべてのスレッドがまったく同じオブジェクトで同期する必要があります。通常、private finalオブジェクトはロックするのが最適です。
private final Collection<...> myCollection = ...
...
synchronize (myCollection) {
myCollection.add(...);
}
一般的なパターンは、保護しているオブジェクトをロックすることですが、実際には任意の定数オブジェクトにすることができます。次のこともできます。
private final Object lockObject = new Object();
...
synchronize (lockObject) {
myCollection.add(...);
}
したがって、add()メソッドを同期しても、Xの多くのインスタンスがadd()を呼び出してコレクションに挿入するのを止めることはできません。したがって、スレッドの問題が発生する可能性がありますか?
アプリケーションの他の部分がブロック内にmyCollection なくsynchronized (myCollection)てもアクセスしている場合は、はい、スレッドの問題が発生します。コレクションを適切に保護し、メモリバリアを提供するには、すべてのアクセスを同期する必要があります。つまりadd(...)、、、contains(...)イテレータなどです。
多くの場合、コレクションまたは他のクラスを保護しようとしている場合は、同期を行うクラスでそれをラップするのが理にかなっています。synchronizedこれにより、ロックが非表示になり、ブロックが欠落しているコードからの意図しない変更からコレクションが保護されます。