Документация (раздел «Семантика») объясняет, что есть только два возможных сценария, которые могут привести к неправильному поведению:
- Побочные действия могут привести к недетерминизму
- Неассоциативные операции приводят к недетерминизму
Первое, что вы заметили сами с println
утверждениями. Второй легко проверяется с помощью неассоциативной двоичной операции, такой как вычитание:
val list = (1 to 100).toList
val a = list.par.reduce(_ - _)
println(a)
Попробуйте выполнить приведенный выше фрагмент кода пару раз.
Список целых чисел может отображаться параллельно несколькими рабочими, потому что элементы не зависят друг от друга. Каждый работник может выполнить операцию на месте, не затрагивая любой другой элемент. Таким образом, даже если поначалу, возможно, это не интуитивно понятно, такая обработка выигрывает от при распараллеливании (но, чтобы улучшение было заметным, вам, вероятно, потребуется большее количество элементов).
Однако этот же список не может быть сокращен параллельно с неассоциативной операцией, потому что элементы действительно зависят друг от друга, и это имеет большое значение, если вы делаете:
1 - (2 - (3 - 4))
или
((1 - 2) - 3) - 4
Именно поэтому параллельная обработка коллекции обычно поддерживает reduce
и fold
, но не foldLeft
и foldRight
.