使用BlockingQueue时是否需要额外的同步?

时间:2010-09-07 17:55:40

标签: java multithreading synchronization

我有一个简单的bean @Entity Message.java,它有一些正常的属性。该对象的生命周期如下

消息的实例化发生在线程A上,然后排入阻塞队列

池中的另一个线程获取该对象并使用它执行一些操作并更改Message的状态,之后,对象再次进入blockingQueue。重复该步骤直到条件使其停止。每次对象获取读/写时都可能来自不同的线程,但保证一次只有一个线程可以读/写。

鉴于这种情况,我是否需要同步getter / setter?也许这些属性会变化?或者我可以在没有同步的情况下离开?

谢谢,希望我能澄清一下我在这里的情况。

4 个答案:

答案 0 :(得分:28)

不,您不需要同步对象属性的访问权限,甚至不需要对成员变量使用volatile

线程在BlockingQueue上对象排队之前执行的所有操作“在对象出列之前发生。这意味着第一个线程所做的任何更改都是第二个线程可见的。这是并发集合的常见行为。请参阅the BlockingQueue class documentation.

的最后一段

只要第一个线程在排队对象后没有进行任何修改,它就是安全的。

答案 1 :(得分:3)

您不需要自己进行同步,因为队列已经为您完成了同步。

可见性也得到保证。

答案 2 :(得分:2)

如果您确定一次只有一个线程可以访问您的对象,那么您不需要同步。

但是,您可以通过使用synchronized关键字来确保:每次要访问此对象并确保没有其他线程正在使用同一个实例时,请将代码包装在同步块中:

Message myMessage = // ...
synchronized (myMessage) {
    // You're the only one to have access to this instance, do what you want
}

synchronized块将获取myMessage对象的隐式锁定。因此,在您离开此块之前,没有其他同步块可以访问同一个实例。

答案 3 :(得分:0)

听起来你可以离开同步的方法。 synchronized只是锁定对象,只允许一个线程访问它。你已经使用阻塞队列处理了这个问题。

易失性会很好用,因为这可以确保每个线程都有最新版本,而不是线程本地缓存值。