以下代码段是否会针对迭代范围的所有索引正确写入results
?
虽然有多个线程同时访问同一个对象;由于索引,每个线程都在写入内存中的唯一位置。
let results:NewType[] = Array.zeroCreate temp.Length
let mutable data = Unchecked.defaultof<OldType>
let loopResult =
System.Threading.Tasks.Parallel.For(
0,
temp.Length,
(fun i ->
data <- temp.[i]
results.[i] <- NewType(data.X, data.Y)
)
)
答案 0 :(得分:5)
您编写此代码的方式,在并行迭代中它将无法正常运行。您添加了一个可变的临时对象,这会破坏您安全地并行化此代码的能力。写入结果是安全的,因为您知道每个线程将访问数组的不同元素,但写入数据是不安全的,因为许多线程可以分配给该可变对象在同一时间。
如果您重建代码:
let results:NewType[] = Array.zeroCreate temp.Length
let loopResult =
System.Threading.Tasks.Parallel.For(
0,
temp.Length,
(fun i ->
let data = temp.[i]
results.[i] <- NewType(data.X, data.Y)
)
)
这种行为将是安全的。
然而,这段代码只是简单的并行映射,因此以这种方式编写它会更加惯用:
let loopResult = temp |> Array.Parallel.map (fun data -> NewType(data.X, data.Y))
答案 1 :(得分:1)