Java 在线程安全对象上进行同步是否会阻止可能操纵它的其他调用?

Java 在线程安全对象上进行同步是否会阻止可能操纵它的其他调用?,java,concurrency,Java,Concurrency,假设我创建了一个线程安全对象: PriorityBlockingQueue<Object> safeQueue = new PriorityBlockingQueue<Object>(); 代码是否会阻止: // some non-synchronized block Object value = safeQueue.poll(); 不会。只有当另一个线程也在同一个对象上执行synchronized时,才会出现阻塞。如果您的代码是synchronized(safeQu

假设我创建了一个线程安全对象:

PriorityBlockingQueue<Object> safeQueue = new PriorityBlockingQueue<Object>();
代码是否会阻止:

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

不会。只有当另一个线程也在同一个对象上执行
synchronized
时,才会出现阻塞。如果您的代码是
synchronized(safeQueue)
的,则调用
PriorityBlockingQueue.poll()
只会在
poll()
synchronized
方法或者使用的代码是
synchronized(this)
代码时阻塞

调用
safeQueue.poll()
时,
PriorityBlockingQueue
代码实际上使用的是内部
ReentrantLock
,而不是执行
同步(this)
。以下是
poll()
的代码:


最后,正如您所提到的,
PriorityBlockingQueue
已经是可重入的,因此您不需要在其上进行同步以允许多个线程访问队列。当然,如果您需要在自己的代码中解决争用条件,您仍然需要在其上进行同步。

如果对象本身具有在实例上同步的方法,则有可能。例如:

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

class MyClass {

    // foo needs a lock on this
    public synchronized void foo() { 
       ...
    }
}
现在,调用
c.foo()同步的
部分之外的code>仍将阻塞


例如,旧的Java
Vector
类是这样在内部同步的,因此从外部锁定对象可能会干扰内部锁定。

简单的回答是:这取决于线程安全类的线程安全性来自何处

如果您想沿着这条路线走下去,您必须依赖于类的文档或其实现代码(注意未来版本中的更改…),或者采取防御措施,不信任它,而是根据原子性需要在另一个对象上进行同步(或其他任何同步)


它当然不需要阻塞,特别是因为许多
java.util.concurrent
类都是非阻塞类(因此它们本身不同步以实现线程安全)。另一方面,如果类从
synchronized(this)
(或者相当于
synchronized
实例方法)获得其线程安全性,那么是的,这将阻塞。这方面的一个例子是从
集合.synchronizedMap
返回的映射,其中记录了该阻塞,并且实际上是一个预期的功能(以便您可以自动查询和修改映射).

同步的
和线程安全的对象彼此之间没有任何关系。@SLaks我可以使用synchronized使对象线程安全,是吗?@SLaks:不正确。如果对象在
上进行内部同步,那么如果从外部锁定对象,您可能会遇到麻烦。@Tudor:正确写入的线程安全对象不会锁定
@SLaks:如果所有线程安全对象都“正确写入”…轮询()为了保证线程安全,操作必须在对象上执行某种同步?当然可以,但这是在对象@Ben内部处理的。您不能假设它通过调用
synchronized(this)
工作。我编辑了我的答案,以显示
poll()
方法锁定的内容。我认为它所做的不是同步(这一点),但认为可能有一些重叠。感谢您花时间解释!当然是的,没有“重叠”。您在同一对象上进行了
同步
,或者未同步。或者您正在使用相同的
ReentrantLock
或其他锁结构。事实上,作为更一般的经验法则,“同步”锁是一种独立的方法,用于锁定/同步Java 5并发实用程序,如阻塞队列、锁存、锁等。我最终使用了集合同步方法来完成我想要的操作。
MyClass c = new MyClass();
synchronized(c) {
    ...
}
class MyClass {

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