让 info = new SortedDictionary<string, string> ... 线程 A -------- info.Add("abc", "def") 线程 B -------- 信息 |> Seq.iteri (fun i value -> ...
当我使用 iteri 函数时,我应该把 readLock 放在哪里?
让 info = new SortedDictionary<string, string> ... 线程 A -------- info.Add("abc", "def") 线程 B -------- 信息 |> Seq.iteri (fun i value -> ...
当我使用 iteri 函数时,我应该把 readLock 放在哪里?
您可能只想回避可变性问题,并使用不可变 Map 而不是 SortedDictionary。这样,您的迭代就可以在数据结构的“快照”上运行,而不必担心它会从您的下方被更改。然后,您只需要锁定您最初抓取的快照。
例如(警告,尚未测试这是否实际上是线程安全的!):
let mymap = ref Map<string,string>.Empty
let safefetch m = lock(m) (fun () -> !m)
let safeadd k v m = lock(m) (fun () -> m := Map.add k v !m)
mymap
|> safefetch
|> Map.iter ( fun k v -> printfn "%s: %s" k v )
mymap |> safeadd "test" "value"
经过一番思考,似乎在 Seq.iteri 上加锁实际上没有任何意义,因为 Seq 在 F# 中是惰性的。
然而,有趣的是,在序列的迭代过程中,当另一个线程插入字典的附加元素时会引发异常。不确定这对于惰性迭代是否完全有保证。
我现在的解决方案(作为一个函数)是:
(有趣_-> 锁定信息(有趣_-> 信息 |> Seq.iteri (fun ix -> ...)))
我希望可以回答我自己的问题(我是新来的)。