【发布时间】:2020-08-13 19:02:04
【问题描述】:
我发现了很多与可见性、同步和线程相关的问题和答案,但似乎都没有涵盖我的特定用例(或者我可能只是不擅长搜索;-)所以我会问一个新问题并希望一些慷慨的灵魂能启发我:)
我的问题是:鉴于下面的代码,访问主线程中 WorkItem 项的字段是否会正确反映线程池工作线程对它们所做的任何更改?
我的怀疑是“否”,因为这感觉类似于传递一个包含一些值的数组,只是在数组引用上同步,而不是在单个元素上同步...... JDK 中存在像 AtomicReferenceArray 这样的类肯定是有原因的以及为什么他们在访问单个元素时使用 getVolatile()/setVolatile()。
package com.voipfuture.voipmng.monitoring;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class IsThisThreadSafe
{
public static class WorkItem { public String field1,field2; /* etc. */ }
public static void main(String[] args) throws InterruptedException
{
final ExecutorService service = Executors.newFixedThreadPool(5);
final List<WorkItem> items = List.of(new WorkItem(), new WorkItem());
final CountDownLatch finished = new CountDownLatch(items.size());
for (WorkItem item : items)
{
service.submit(() ->
{
try
{
synchronized (item)
{
// mutate object
item.field1 = "test";
}
}
finally
{
finished.countDown();
}
});
}
finished.await();
for (WorkItem item : items)
{
// will this make sure all changes done inside
// threadpool worker threads are visible here ?
synchronized (item)
{
// do stuff with work item
System.out.println(item.field1);
}
}
}
}
【问题讨论】:
-
我强烈推荐使用标准的 Java 代码格式;在这种情况下,它会将代码的垂直大小减少约 25%。另外,如果您要处理多线程,我强烈建议您了解 happens-before 概念(特别是 POJO 上的操作发生在同一线程中的其他任何事情之前,以及闩锁倒计时发生在等待之前)。
标签: java multithreading synchronization thread-safety