Я улучшаю существующий алгоритм, который состоит из нескольких независимых шагов для использования параллельных задач. Каждая из задач создаст несколько объектов для хранения своих результатов. В конце концов, я хотел бы иметь список всех результатов для возврата из метода управления. На данный момент мой код выглядит как-то такНужно ли мне синхронизировать результат вызова invokeAll?
private final ExecutorService pool = ...;
// A single task to be performed concurrently with other tasks.
private class WorkHorse implements Callable<Void> {
private final Collection<X> collect;
public WorkHorse(Collection<X> collect, ...) {
this.collect = collect;
}
public Void call() {
for (...) {
// do work
synchronized (this.collect) {
this.collect.add(result);
}
}
return null;
}
}
// Uses multiple concurrent tasks to compute its result list.
public Collection<X> getResults() {
// this list is supposed to hold the results
final Collection<X> collect = new LinkedList<X>();
final List<WorkHorse> tasks = Arrays.asList(
new WorkHorse(collect, ...), new WorkHorse(collect, ...), ...);
this.pool.invokeAll(tasks);
// ## A ##
synchronized (collect) {
return collect;
}
}
ли я на самом деле нужна synchronized
на «## A ##» для обеспечения соблюдения происходит, прежде, чем отношения с модифицирующими операциями в задачах рабочих? Или я могу полагаться на все операции записи, которые произошли после того, как invokeAll
вернется и будет видимым для управляющего потока? И есть ли причина, почему я не должен возвращать коллекцию результатов из своего собственного блока synchronized
?
Кроме того, если это были * не * семантика invokeAll(), синхронизированный блок не помог бы. Казалось бы, вам нужны какие-то ворота, которые предотвратили бы продолжение, пока все остальные потоки не будут написаны. – Avi
Брайан Гетц говорит в «Java Concurrency in Action», что «все [поток] A, сделанное в или до синхронизированного блока, видимо [thread] B, когда он выполняет синхронизированный блок, защищенный одной и той же блокировкой. нет такой гарантии ». Утверждение в документации invokeAll, похоже, не отменяет это требование или делает это? – janko
@janko Это утверждение верно, но не было гарантии, что ваш синхронизированный обратный блок не будет запущен до того, как все рабочие потоки достигнут синхронизированной части. invokeAll говорит, что потоки уже выполнили всю свою работу (т. Е. Достигли возврата null;), когда она вернется. – Zed