gpt4 book ai didi

concurrency - F# 解决死锁

转载 作者:行者123 更新时间:2023-12-02 04:48:15 26 4
gpt4 key购买 nike

我是并发编程的新手,所以我有一个死锁的小问题需要解决。

所以对于下面的这段代码,它没有打印出任何我怀疑一定存在死锁的东西,尽管我不太确定它是如何发生的。

let sleepMaybe() = if (random 4) = 1 then Thread.Sleep 5

type account(name:string) =
let balance = ref 1000
member this.Balance = lock this <| fun () -> !balance
member this.Name = name
member this.Withdraw amount = balance := !balance - (sleepMaybe(); amount)
member this.Deposit amount = balance := !balance + (sleepMaybe(); amount)

member this.Transfer (toAcc:account) amount =
lock this <| fun () -> lock toAcc <| fun () -> toAcc.Deposit amount
this.Withdraw amount


let doTransfers (acc:account) (toAcc:account) () =
for i in 1..100 do acc.Transfer toAcc 100
printfn "%s balance: %d Other balance: %d" acc.Name acc.Balance toAcc.Balance

let q2main() =
let acc1=account("Account1")
let acc2=account("Account2")

startThread (doTransfers acc1 acc2)
startThread (doTransfers acc2 acc1)

q2main()

最佳答案

您正在锁定实例本身并要求两个实例都被锁定以传输某些内容。这是导致死锁的秘诀。

  • 线程 1 锁定 acc1 以开始传输
  • 线程 2 锁定 acc2 以开始传输
  • 线程 1 等待 acc2 上的锁被释放,以便完成传输
  • 线程 2 等待 acc1 上的锁被释放,以便完成传输

他们会无限期地等待对方释放他们的锁。

如果您必须一次获取多个锁,总是以相同的顺序获取锁。也就是说,尽量不要通过更改对象职责同时需要多个锁。

例如,取款和存款是两个不相关的独立操作,但它们会修改余额。你正试图用锁来保护余额。一旦帐户的余额发生变化,就没有必要再保留该锁定。此外,我建议知道如何转移到其他帐户不是帐户的责任。

考虑到这一点,以下是消除死锁的更改。

type Account(name:string) =
let mutable balance = 1000
let accountSync = new Object()

member x.Withdraw amount = lock accountSync
(fun () -> balance <- balance - amount)
member x.Deposit amount = lock accountSync
(fun () -> balance <- balance + amount)

let transfer amount (fromAccount:Account) (toAccount:Account) =
fromAccount.Withdraw(amount)
toAccount.Deposit(amount)

关于concurrency - F# 解决死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19385950/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com