我可以(安全地)在Parallel.For循环结构中写入数组吗?

时间:2015-10-26 13:43:09

标签: .net multithreading parallel-processing f#

以下代码段是否会针对迭代范围的所有索引正确写入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) 
        )
    )

2 个答案:

答案 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)

由于F#数组的类型通常是.NET System.Array同时写入数组的不同部分将是线程安全的。已经讨论过HEREHERE