【发布时间】:2020-10-08 01:26:07
【问题描述】:
考虑以下代码:
private static final Object LOCK = new Object();
private static final ExecutorService executorService = Executors.newFixedThreadPool(10); // Also used for a few other tasks.
public static void save(Object o) {
String s = serialize(o);
executorService.submit(() -> {
// Do we have a race condition here?
synchronized (LOCK) {
saveToFile(s, new File("test.txt")); // overwrites the file
}
});
}
public static void main(String[] args) {
save(args[0]);
save(args[1]);
}
save(Object o) 仅在主线程上调用。我知道线程池按顺序处理内部队列中提交的任务,但理论上会不会发生,在达到synchronized (LOCK) 之前存在竞争条件并且文件输出为args[0]?
如果是,如何避免这种情况?我知道单线程执行器肯定会解决这个问题,但如果可能的话我想使用这个线程池。
编辑:我认为一种可能的方法是使用Queue:
private static final Queue<String> queue = new ConcurrentLinkedQueue<>();
public static void save(Object o) {
queue.add(serialize(o));
executorService.submit(() -> {
synchronized (LOCK) {
saveToFile(queue.remove(), new File("test.txt"));
}
});
}
【问题讨论】:
-
" 在达到
synchronized (LOCK)之前存在竞争条件" --> 是的。 " 文件输出是args[0]" --> 并非总是如此,这取决于比赛的结果。但是,你想避免什么? -
@boobalan 竞争条件。输出应保证为
args[1]。 -
如果
args[1]是你想要的输出,你为什么叫args[0]?或者你需要输出args[1],只是因为它是最后一个提交的? -
我想我找到了一种方法,但是我想知道是否有更好的解决方案。
-
您可以创建一个锁、一个条件和一个通用计数器,每次程序都会等待最后一个完成。
标签: java multithreading thread-safety race-condition synchronized