我有一个简单的bean @Entity Message.java,它有一些正常的属性。该对象的生命周期如下
消息的实例化发生在线程A上,然后排入阻塞队列
池中的另一个线程获取该对象并使用它执行一些操作并更改Message的状态,之后,对象再次进入blockingQueue。重复该步骤直到条件使其停止。每次对象获取读/写时都可能来自不同的线程,但保证一次只有一个线程可以读/写。
鉴于这种情况,我是否需要同步getter / setter?也许这些属性会变化?或者我可以在没有同步的情况下离开?
谢谢,希望我能澄清一下我在这里的情况。
答案 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只是锁定对象,只允许一个线程访问它。你已经使用阻塞队列处理了这个问题。
易失性会很好用,因为这可以确保每个线程都有最新版本,而不是线程本地缓存值。