java - 线程池、共享数据、Java同步

标签 java threadpool synchronize

比如说,我有一个数据对象:

class ValueRef { double value; }

每个数据对象存储在主集合中的位置:

Collection<ValueRef> masterList = ...;

我还有一个作业集合,其中每个作业都有一个本地数据对象集合(其中每个数据对象也出现在 masterList 中):

class Job implements Runnable { 
     Collection<ValueRef> neededValues = ...; 
     void run() {
         double sum = 0;
         for (ValueRef x: neededValues) sum += x;
         System.out.println(sum);
     } 
}

用例:

  1. for (ValueRef x: masterList) { x.value = Math.random(); }

  2. 用一些作业填充作业队列。

  3. 唤醒一个线程池

  4. 等到每个作业都被评估过

注意:在工作评估过程中,所有的值都是常量。然而,线程可能在过去评估过作业,并保留缓存的值。

问题:确保每个线程看到最新值所需的最小同步量是多少?

我从监视器/锁的角度理解同步,我不从缓存/刷新的角度理解同步(即内存模型在同步块(synchronized block)的进入/退出时保证了什么)。

对我来说,感觉我应该需要在更新值的线程中同步一次以将新值提交到主内存,并且每个工作线程同步一次以刷新缓存以便读取新值。但我不确定如何最好地做到这一点。

我的方法: 创建一个全局监视器:static Object guard = new Object();然后,在 guard 上同步,同时更新主列表。最后,在启动线程池之前,为池中的每个线程同步一次 guard在一个空 block 中。

这真的会导致该线程读取的任何值都被完全刷新吗?或者只是在同步块(synchronized block)中触及的值?在这种情况下,也许我应该循环读取每个值一次,而不是一个空 block ?

感谢您的宝贵时间。


编辑:我想我的问题归结为,一旦我退出同步块(synchronized block),每次第一次读取(在那之后)是否都进入主内存?不管我同步了什么?

最佳答案

线程池的线程在过去评估过一些作业并不重要。

Executor 的 Javadoc 说:

Memory consistency effects: Actions in a thread prior to submitting a Runnable object to an Executor happen-before its execution begins, perhaps in another thread.

因此,只要您使用标准线程池实现并在提交作业之前更改数据,您就不必担心内存可见性影响。

关于java - 线程池、共享数据、Java同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11215548/

相关文章:

multithreading - Scala Future[T] 是否在内部阻塞? Scala Future 内部会发生什么?

c# - 如何从 CLR 线程池而不是 ASP.NET 池在 ASP.NET 页面中创建线程?

java - Thread.sleep() 和 schedulerExecutorService.scheduleWithFixedDelay 的性能注意事项

php - 如何同步带前缀的mysql表字段

java - Osgi同步服务

java - 如何在编辑器上创建弹出菜单,使其仅在 Package Explorer View 处于 Activity 状态时出现

java - 使用 JAVA 向 LDAP 中的现有用户添加属性

java - 使用 java.util.regex.Matcher 时发生 StackOverflowError

iphone - 奇怪的 NSUserDefaults 行为

java - Spring Integration DSL 中使用 channel 和网关的 Echo 套接字服务