java - 确保线程的 "updates"对 Java 中的其他线程可读

标签 java multithreading caching

我有一个主线程,它将启动其他线程。这些其他线程将要求完成作业,主线程将使作业可供其他线程查看和执行。

必须要做的工作就是将一个巨大的 boolean 数组中的索引设置为true。它们默认为 false,其他线程只能将它们设置为 true,而不能设置为 false。各种作业可能涉及将相同的索引设置为 true。

主线程根据两件事找到新的工作。

  1. 巨大 boolean 数组中的值。
  2. 哪些工作已经完成。

如何确保主线程从巨大的 boolean 数组中读取新值?

我无法通过同步方法更新数组,因为这几乎是所有其他线程所做的,因此我只能获得相当多的顺序性能。

假设其他线程通过非同步函数将其许多索引设置为 true 来更新巨大的 boolean 数组。如何确保主线程读取更新并确保它不仅仅缓存在线程本地?有什么办法让它“推送”更新吗?我猜主线程应该只使用同步方法来“获取”更新?

最佳答案

要真正完整地回答您的问题,您应该打开 Java 语言规范的副本,并搜索“happens before”。

当 JLS 说 A“发生在”B 之前时,这意味着在 Java 语言的有效实现中,A 需要实际发生在 B 之前。该规范规定如下:

  • 如果某个线程更新字段,然后释放锁(例如, 离开同步块(synchronized block)),更新“发生在”锁之前 已发布,

  • 如果某个线程释放锁,而其他线程随后释放锁
    获取相同的锁,释放“发生在”获取之前。

  • 如果某个线程获取锁,然后读取字段,则 获取“发生在”读取之前。

由于“发生在”之前是传递关系,因此您可以推断,如果线程 A 更新同步块(synchronized block)内的某些变量,然后线程 B 检查同一对象上同步的 block 中的变量,那么线程 B 将看到线程 A 写了什么。

除了进入和离开同步块(synchronized block)之外,还有许多其他事件(构造对象、wait()ing/notify()ing对象、start()ing和join()ing线程、读取和写入 volatile 变量)允许您可以在线程之间建立“发生在之前”的关系。

这并不能快速解决您的问题,但这一章值得一读。

<小时/>

...the main thread will make jobs available for the other threads to see and do...

I can't have the update of the array be through a synchronized method, because that's pretty much all the other threads do, and ...

听起来你是说每个工作线程在必须等待来自 main() 线程的进一步指令之前只能完成少量的工作。如果这是真的,那么大多数 worker 大部分时间都会在等待。如果您只在一个线程中完成所有工作,您可能会获得更好的性能。

假设您的目标是充分利用多处理器计算机的可用周期,您将需要以某种方式对工作进行分区,让每个工作线程在需要同步之前完成大部分工作与任何其他线程。

关于java - 确保线程的 "updates"对 Java 中的其他线程可读,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28868832/

相关文章:

java - java `indexOf`对 `float[]`的使用

cocoa - NSOperation 传递给委托(delegate)时导致崩溃

java - 获取与线程和数组列表相关的错误

c# - 为什么线程创建这么快?

php - Silverstripe TinyMCE 在负载均衡器后面崩溃。

ruby-on-rails - 如果 Redis 关闭,则禁用 Rails 缓存

java - Java 中的对象和指针

java - Android View 不响应绘图

java - java中公历的错误

java - 为什么 iBATIS 会给出过时的结果,即使禁用了缓存?