Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用BlockingQueue时是否需要额外的同步?_Java_Multithreading_Synchronization - Fatal编程技术网

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

Java 使用BlockingQueue时是否需要额外的同步?,java,multithreading,synchronization,Java,Multithreading,Synchronization,我有一个简单的bean@Entity Message.java,它有一些普通属性。该对象的生命周期如下所示 消息的实例化发生在线程A上,然后线程A进入blockingQueue 池中的另一个线程获取该对象并对其执行一些操作并更改消息的状态,之后,该对象再次进入blockingQueue。重复此步骤,直到条件使其停止。每次对象读/写时都可能来自不同的线程,但保证一次只有一个线程在读/写对象 在这种情况下,我需要同步getter/setter吗?也许会让这些属性变得不稳定?或者我可以不同步就离开吗

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

消息的实例化发生在线程A上,然后线程A进入blockingQueue

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

在这种情况下,我需要同步getter/setter吗?也许会让这些属性变得不稳定?或者我可以不同步就离开吗


谢谢,希望我能澄清我在这里吃的东西

如果确定一次只有一个线程访问对象,则不需要同步

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

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

同步块将获取myMessage对象上的隐式锁。因此,在您离开此块之前,其他同步块将无法访问同一实例。

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


能见度也得到了保证

听起来你可以把同步的方法从方法中去掉。synchronized只锁定对象,只允许单个线程访问它。您已经通过阻塞队列处理过了


Volatile最好使用,因为这样可以确保每个线程都具有最新版本,而不是线程本地缓存值。

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

线程在对象退出队列之前在
BlockingQueue
中将对象排入队列之前执行的所有操作。这意味着第一个线程所做的任何更改都对第二个线程可见。这是并发集合的常见行为。见本报告最后一段:

内存一致性影响:与其他并发集合一样,在将对象放入另一个线程中的
BlockingQueue
之前线程中的操作,在另一个线程中从
BlockingQueue
访问或移除该元素之后的操作


只要第一个线程在将对象排队后不进行任何修改,它就安全了。

如果两个线程在对象上实际交错,那么同步单个getter和setter并不能真正证明什么。他们仍然会在不一致的状态下看到它/执行部分覆盖。这个答案是解决这个问题的更好方法。@Vivien_Barousse因此,我实际上不需要同步任何内容,因为不会同时访问这些内容。这回答了我的问题,谢谢!使用
volatile
阻塞队列
是不必要的(而且重复工作效率低);
BlockingQueue
契约的一部分是,一个线程在将一个对象放入队列之前所做的任何操作“发生在”另一个线程将该对象移出队列之前。很高兴知道。我知道当另一个线程更改字段的值时,需要volatile。阻塞线程会关心这一点是有道理的,因为当前线程请求值+1来提及BlockingQueue的线程可见性语义。(请复习。)