Java线程安全地将集合对象从一个线程传递到另一个线程

标签 java thread-safety

我有一个 Java 应用程序,它有工作线程来处理作业。一个 worker 产生一个结果对象,比如:

class WorkerResult{
    private final Set<ResultItems> items;
    public Worker(Set<ResultItems> pItems){
         items = pItems;
    }
}

当 worker 完成后,它会执行以下操作:

 ...
 final Set<ResultItems> items = new SomeNonThreadSafeSetImplSet<ResultItems>();
 for(Item producedItem : ...){
      items.add(item);
 }
 passToGatherThread(items);

items 集在这里是一种“工作单元”。 passToGatherThread 方法将 items 集传递给一个收集线程,其中只有一个在运行时存在。

这里不需要同步,因为竞争条件不会发生,因为只有一个线程(Gather-thread)读取items集。 AFAICS,Gather-thread 可能看不到所有项目,因为集合不是线程安全的,对吗?

假设我不能使 passToGatherThread 同步,比如因为它是第 3 方库。我基本上担心的是,由于缓存、VM 优化等原因,收集线程看不到所有项目。所以问题来了:如何以线程安全的方式传递项目集,以便收集线程“看到”正确的项目集?

最佳答案

这里似乎没有同步问题。您为每个 passToGatherThread 创建一个新的 Set 对象,并在修改集合后执行。不会丢失任何对象。

集合(和大多数 Java 集合)可以被许多线程并发访问,前提是集合没有被修改。这就是 Collections.unmodifiableCollection 的用途。

由于提到的passToGatherThread 方法用作与其他线程的通信,它必须使用某种同步——并且每个同步确保线程之间的内存一致性。

此外 - 请注意,对传递的集合中的对象的所有写入都是在传递给其他线程之前进行的。即使内存被复制到线程的本地缓存中,它也具有与另一个线程中相同的未修改值。

关于Java线程安全地将集合对象从一个线程传递到另一个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14812118/

相关文章:

java - 将数据插入到通过 Java 动态更改的 MySql 表中

java - "d"符号在适用于某些对象的方法列表中代表什么?

java - JPA - 实体设计问题

java - 支持 Java 迭代的线程安全排序集合

java - arraylist/atomic double array (Google Guava) 中的 .get() 操作是线程安全的吗?

c# - lock(new object()) -- cargo 崇拜或一些疯狂的 "language special case"?

ios - 修复小型基元的竞争条件有多重要?

Java vector 线程安全

java - for 循环外的变量被更改?

java - 如何创建仅在本地主机上服务的 Java Socket 对象?