我有一个主线程,它将启动其他线程。这些其他线程将要求完成作业,主线程将使作业可供其他线程查看和执行。
必须要做的工作就是将一个巨大的 boolean 数组中的索引设置为true。它们默认为 false,其他线程只能将它们设置为 true,而不能设置为 false。各种作业可能涉及将相同的索引设置为 true。
主线程根据两件事找到新的工作。
- 巨大 boolean 数组中的值。
- 哪些工作已经完成。
如何确保主线程从巨大的 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/