Scalaは、特にこのようなことが起こるため、可変性に対する不変性を奨励します。変更可能な変数val
がある場合、変更を認識していない別のスレッドによって既に読み取られている可能性があります。 すべてのスレッドが * 3のスレッドが0として値和を読んで、そのため、 * 1スレッドは、34
であることを起こるおり、sum + x
を書き込み関数を呼び出すこと:これは、以下の現象が発生する原因となるように並列に合計を行う
並列、加算は任意の順序で行われます * 1さらにスレッドは * 2のスレッドが17を読み取る前に値0を読み込んでいるため、と計算され、0 + 17
(*が17だったとします)と計算します* *最初の3つのスレッドの最後には、0が読み込まれたので、0 + 9
が書き込まれます。
TLDRでは、複数のスレッドが他のスレッドが書き込みを行っている間に読み込み、互いの変更を上書きするため、メモリへの読み取りと書き込みが同期しなくなります。
解決策は、これを順番に実行する方法を見つけることです。パラレル化を非破壊的に活用することです。合計のような関数はfoldLeft、例えば、順番に、または常に新しい値を生成する方法で行うべきである:
Seq(1, 2, 3, 4).foldLeft(0){case (sum, newVal) => sum + newVal}
それとも、和のサブセットを作成しparalelでそれらを追加し、追加funcitonを書くことができますそれらのすべてを順番に一緒に:
Seq(1, 2, 3, 4, 5, 6, 7, 8).grouped(2).toSeq.par.map {
pair =>
pair.foldLeft(0){case (sum, newVal) => sum + newVal}
}.seq.foldLeft(0){case (sum, newVal) => sum + newVal}
返信ありがとうございます。 2番目のforeach(変数sumがどのスレッドで更新されたかを追跡する)のように突然変異をトレースする方法はありますか?それが私の本来の目標でした。 –
@StanleyZhang申し訳ありませんが、私は良い答えがありません。 –