想用 wait/notify 和 map 来实现一个线程写入,另一个线程随后读出的同步处理。
但是遇到了 happens-before 问题。
一个可以复现的代码如下:
import java.time.LocalDateTime;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MainConcurrentHashmapTest {
private static ExecutorService executorService = Executors.newFixedThreadPool(2);
public static void main(String[] args) {
for (int i = 0; i != 100000; ++i) {
test();
}
executorService.shutdown();
}
public static void test() {
final Map<String, Object> map = new ConcurrentHashMap<String, Object>();
final Object mutex = new Object();
final String key = UUID.randomUUID().toString();
Runnable consumer = new Runnable() {
@Override
public void run() {
synchronized (mutex) {
try {
mutex.wait(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object value = map.remove(key);
if (value == null) {
System.out.println("got null value for key = " + key);
}
}
}
};
Runnable producer = new Runnable() {
@Override
public void run() {
map.put(key, LocalDateTime.now().toString());
synchronized (mutex) {
mutex.notify();
}
}
};
executorService.submit(consumer);
executorService.submit(producer);
}
}
运行的时候会发现,有时候得不到最新的 value 值,如下:
got null value for key = f972a078-c314-4cd1-a5e4-d3ce11195a7e
got null value for key = 6ef9476c-8ded-43ec-900e-5f859eeaec1e
got null value for key = 8ecff482-eb9a-4e63-8eee-c950a485fbb0
为什么呢?有什么改进建议么?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.