スレッド セーフなオブジェクトを作成するとします。
PriorityBlockingQueue<Object> safeQueue = new PriorityBlockingQueue<Object>();
同期する場合:
synchronized (safeQueue) {
....
}
ブロックするコード:
// some non-synchronized block
Object value = safeQueue.poll();
スレッド セーフなオブジェクトを作成するとします。
PriorityBlockingQueue<Object> safeQueue = new PriorityBlockingQueue<Object>();
同期する場合:
synchronized (safeQueue) {
....
}
ブロックするコード:
// some non-synchronized block
Object value = safeQueue.poll();
いいえ。ブロッキングが発生するのは、別のスレッドも同じsynchronized
オブジェクトに対してa を実行している場合のみです。コードがメソッドである場合、またはコードがコードを使用している場合にのみsynchronized (safeQueue)
、への呼び出しがPriorityBlockingQueue.poll()
ブロックされます。poll()
synchronized
synchronized (this)
コード を呼び出すとsafeQueue.poll()
、実際にはinternal が使用され、. のコードは次のとおりです。PriorityBlockingQueue
ReentrantLock
synchronized (this)
poll()
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return q.poll();
} finally {
lock.unlock();
}
}
最後に、あなたが言及したように、PriorityBlockingQueue
すでに再入可能であるため、複数のスレッドがキューにアクセスできるようにするために同期する必要はありません。もちろん、独自のコードで競合状態を解決する必要がある場合は、同期する必要があります。
簡単に言えば、スレッド セーフ クラスのスレッド セーフがどこから来るかによって異なります。
そのルートをたどりたい場合は、クラスのドキュメントまたはその実装コードに依存する必要があります (将来のバージョンでの変更に注意してください...)。 (または同期している他のもの)。
特に、多くのjava.util.concurrent
クラスが非ブロックであるため (したがって、スレッド セーフを実現するためにクラス自体を同期しないため)、ブロックする必要はありません。一方、クラスがsynchronized(this)
(または同等のsynchronized
インスタンス メソッド) からスレッド セーフを取得する場合、はい、それはブロックされます。この例は、 から返されたマップです。このCollections.synchronizedMap
ブロックでは、ブロックが文書化されており、実際には意図された機能です (マップをアトミックにクエリおよび変更できるようにするため)。
オブジェクト自体に、インスタンスで同期されるメソッドがある場合は可能です。例えば:
MyClass c = new MyClass();
synchronized(c) {
...
}
とMyClass
は:
class MyClass {
// foo needs a lock on this
public synchronized void foo() {
...
}
}
c.foo();
これで、セクションの外側への呼び出しは、synchronized
上記のコードと並行して実行された場合でもブロックされます。
たとえば、古いJavaVector
クラスはこのように内部で同期されていたため、外部からオブジェクトをロックすると、内部ロックが妨げられる可能性があります。