当前位置: 首页 > 知识库问答 >
问题:

BlockingQueue在任何时候对所有线程都是一样的吗?

宿丰
2023-03-14

我正在实现一个程序,主线程将各种消息推送到工作线程,工作线程将工作结果推送回主线程。

为此,我计划使用两个队列,一个推送到工作线程,另一个从中拉出。

据我所知,线程缓存对象,因此,如果它们要将对象添加到另一个线程可以轮询的队列中,则此更改可能不会立即可见,即它可能不会同步。这是正确的吗?

但是,如果我要使用BlockingQueue,则该队列上的所有操作都应该对所有线程立即可见?

共有3个答案

蔡宏大
2023-03-14

BlockingQueue接口的javadoc是这样说的:

“BlockingQueue实现是线程安全的。所有排队方法都使用内部锁或其他形式的并发控制以原子方式实现其效果。”

因此,可以保证一个线程对队列所做的更改“立即”对其他线程可见。。。在记忆模型的意义上。同步put和poll调用已完成。(任何缓存效果都由javadoc中提到的机制来处理。)

当然,这并不意味着他们所有人都会看到语义级别的变化。这取决于线程调度等事情。(如果一个对象被添加到队列中,只有一个线程能够删除它。如果它在第二个线程看到队列状态之前这样做......无论出于什么原因......第二个线程不会注意到添加了一个条目,然后又删除了。)

“立即”的粒度也未指定。例如,如果JVM只使用一个CPU/内核,那么线程只能在发出put调用的线程取消调度后(无论出于何种原因)从轮询返回。此外,刷新内存缓存中的更改需要相当长的时间。

这假设实现类满足“契约”。。。但如果没有,那就是马车

党权
2023-03-14

根据你最初的问题和评论,你混淆了两件不同的事情。

任何实现BlockingQueue的东西都是线程安全的并且可以正确发布。实现该接口的类的内部各不相同,因此“该队列上的所有操作都应该对所有线程立即可见”的说法对于立即的某些定义可能不正确。“非常快”将是一个更恰当的描述;它可能没有使用阻塞/锁定机制,并且总是涉及线程调度。

安全发布(线程缓存)与Java中线程的工作方式有关,是一个更大的主题。必须安全地发布对该BlockingQueue的引用,以便所有线程都能看到它。在大多数情况下,当使用这样的结构时,您可能做了正确的事情。也就是说,要么将引用传递给可运行的构造函数,要么将其创建为某个地方的最终变量。但实际上,只要你没有得到NullPointerException。。。线程可以看到它。

当您将对象传递给多个线程后,在对象内部实例化某个对象时,就会出现安全发布问题。

关于这个主题的实际参考是Java并发,值得拥有。

严开宇
2023-03-14

这个答案假设您谈论的是线程安全的数据结构或构造。如果使用常规的非线程安全字段,则不能保证它会工作,但也不能保证它不会工作。注意:这是线程安全的单元测试有用,但不是傻瓜式的。

此更改可能不会立即可见,即可能不会同步。这是正确的吗?

对延迟通常为50-100纳秒,因此可能几乎是立即发生的。

此队列上的所有操作都应该对所有线程立即可见?

这在真正的机器中是不可能的。你可以说的是,你永远不会因为可视性问题而出错,主要是非常轻微的延迟。(但是,由于它会产生垃圾,因此在最坏的情况下,如果机器没有Hibernate,您可以获得完全的GC延迟,在这种情况下,延迟可能是数小时或数天)

 类似资料:
  • 问题内容: 我在另一个Stack Overflow问题上读到,Python就像Ruby一样,因为它涉及到“一切都是对象”,而Python中的一切都是对象,就像Ruby一样。 这是真的?Python中的所有对象都是像Ruby这样的对象吗? 两者在这方面有何不同?或者它们真的相同吗?例如,您能拿一个数字来做我所看到的Ruby吗: 可以在Python中以相同的方式完成吗? 问题答案: DiveIntoP

  • 我知道了 所有指针具有相同的大小是很常见的,但是指针类型具有不同的大小在技术上是可能的。 但是后来我看到这个上面写着: 虽然指针的大小都一样,因为它们只存储一个内存地址,但我们必须知道它们指向的是什么类型的东西。 现在,我不确定哪一个是正确的。第二个引用的陈述看起来像是来自佛罗里达州立大学计算机科学的注释。 以下是我的想法: 说我们有: 现在,假设C标准允许指针有不同的大小。进一步假设在某些任意机

  • 问题内容: 我知道文档说明该对象是线程安全的,但这是否意味着从所有方法对其进行的所有访问都是线程安全的?因此,如果我一次从多个线程中调用它,并且一次在同一实例上调用它,会不会发生什么不好的事情? 问题答案: 快速答案是肯定的,它们是线程安全的。但是不要让它在那里… 首先,一个小的内部管理是一个接口,任何不是线程安全的实现都将破坏书面合同。您包括的链接是指,它具有一定的灵巧性。 您包含的链接引起了一

  • 问题内容: 我在许多JavaScript简介中都读了很多。我只是不明白。我一直认为对象是具有方法和属性的东西。我了解数组,因为它具有键值对。“字符串”或“数字”或“函数”怎么样?上面列出的这些东西对我来说就像是功能。这意味着您输入了一些东西,然后得到了一些东西。您实际上并没有获得访问属性或其他任何内容。在数组或“对象”列表中没有使用点符号。 是否有人用点符号编写每个方法的示例示例,这些示例的方法和

  • 我正在使用invokeAll()调用线程列表。AFAIK invokeAll()仅在所有线程完成其任务时才返回。 当所有线程完成时调用 它将停止发生异常的线程,而不停止其余的线程。如果任何一个线程抛出异常,是否有一种方法可以停止所有其他线程?或者我必须提交每个任务而不是invokeAll()?? 按照沃尔特苏的建议,我试着 发生异常时,此操作不会停止

  • 问题内容: 这是我昨晚被拒绝的采访中唯一无法回答的两个问题。 问题答案: 问:什么时候应该使用多线程? 答:“您的问题非常广泛。只有很少的一个线程可以简单,快速和可靠地满足功能,这是非平凡的系统。例如:[选择目标公司出售的典型系统并挑选一个它的功能的两个方面会更好地发挥作用- 繁重的CPU,通信,多用户-只是选择一些可能的原因并进行解释]。 问:如果不同的线程执行相互独立的任务,多线程会有所好处吗