3

スレッド セーフなオブジェクトを作成するとします。

PriorityBlockingQueue<Object> safeQueue = new PriorityBlockingQueue<Object>();

同期する場合:

synchronized (safeQueue) {
   ....
}

ブロックするコード:

// some non-synchronized block
Object value = safeQueue.poll();
4

3 に答える 3

4

いいえ。ブロッキングが発生するのは、別のスレッド同じsynchronizedオブジェクトに対してa を実行している場合のみです。コードがメソッドである場合、またはコードがコードを使用している場合にのみsynchronized (safeQueue)、への呼び出しがPriorityBlockingQueue.poll()ブロックされます。poll()synchronizedsynchronized (this)

コード を呼び出すとsafeQueue.poll()、実際にinternal が使用され、. のコードは次のとおりです。PriorityBlockingQueueReentrantLocksynchronized (this)poll()

public E poll() {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        return q.poll();
    } finally {
        lock.unlock();
    }
}

最後に、あなたが言及したように、PriorityBlockingQueueすでに再入可能であるため、複数のスレッドがキューにアクセスできるようにするために同期する必要はありません。もちろん、独自のコードで競合状態を解決する必要がある場合は、同期する必要があります。

于 2012-05-11T22:36:22.390 に答える
2

簡単に言えば、スレッド セーフ クラスのスレッド セーフがどこから来るかによって異なります。

そのルートをたどりたい場合は、クラスのドキュメントまたはその実装コードに依存する必要があります (将来のバージョンでの変更に注意してください...)。 (または同期している他のもの)。

特に、多くのjava.util.concurrentクラスが非ブロックであるため (したがって、スレッド セーフを実現するためにクラス自体を同期しないため)、ブロックする必要はありません。一方、クラスがsynchronized(this)(または同等のsynchronizedインスタンス メソッド) からスレッド セーフを取得する場合、はい、それはブロックされます。この例は、 から返されたマップです。このCollections.synchronizedMapブロックでは、ブロックが文書化されており、実際には意図された機能です (マップをアトミックにクエリおよび変更できるようにするため)。

于 2012-05-11T23:28:37.740 に答える
0

オブジェクト自体に、インスタンスで同期されるメソッドがある場合は可能です。例えば:

MyClass c = new MyClass();
synchronized(c) {
    ...
}

MyClassは:

class MyClass {

    // foo needs a lock on this
    public synchronized void foo() { 
       ...
    }
}

c.foo();これで、セクションの外側への呼び出しは、synchronized上記のコードと並行して実行された場合でもブロックされます。

たとえば、古いJavaVectorクラスはこのように内部で同期されていたため、外部からオブジェクトをロックすると、内部ロックが妨げられる可能性があります。

于 2012-05-11T22:43:52.380 に答える