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>仍将阻塞
例如,旧的JavaVector
类是这样在内部同步的,因此从外部锁定对象可能会干扰内部锁定。简单的回答是:这取决于线程安全类的线程安全性来自何处
如果您想沿着这条路线走下去,您必须依赖于类的文档或其实现代码(注意未来版本中的更改…),或者采取防御措施,不信任它,而是根据原子性需要在另一个对象上进行同步(或其他任何同步)
它当然不需要阻塞,特别是因为许多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() {
...
}
}