0
我创建了一个名为ticket的可变列表,其中包含Ticket类型。 我也有一个bookSeat函数,它可以模拟预订座位。由于F#列表类型是不可变的,我的bookSeat函数总是返回一个新的,修改后的票据列表副本。如何在多线程中的函数内实现锁定f#
open System
open System.Threading
type Ticket = {seat:int; customer:string}
let mutable tickets = [for n in 1..10 -> {Ticket.seat = n; Ticket.customer = ""}]
let bookSeat _ =
Console.WriteLine("Enter seat number: ")
let seatNo = int(Console.ReadLine())
Console.WriteLine("Enter customer name: ")
let name = string(Console.ReadLine())
let book seatNo name tickets =
tickets |> List.map (fun ticket ->
if ticket.seat = seatNo then { ticket with customer = name }
else ticket)
tickets <- book seatNo name tickets
我现在想创建两个线程,既调用bookSeat,我想在bookSeat中实现锁定以避免竞争条件。
我想出了这个新的bookSeat功能(仍编程和F#很新,代码可能会显得很菜鸟issh)
let seatNo = ref 0
let name = ref ""
let bookSeat _ =
Console.WriteLine("Enter seat number: ")
seatNo := int(Console.ReadLine())
Console.WriteLine("Enter customer name: ")
name:= string(Console.ReadLine().ToString())
let book seatNo name tickets =
lock(seatNo,name) (fun()-> tickets |> List.map (fun ticket ->
if ticket.seat = seatNo then { ticket with customer = name }
else ticket))
tickets <- book !seatNo !name tickets
ThreadPool.QueueUserWorkItem(new WaitCallback(bookSeat)) |> ignore
ThreadPool.QueueUserWorkItem(new WaitCallback(bookSeat)) |> ignore
Thread.Sleep(5000)
代码编译成功,但是当我运行它有一个错误。它输出该紧随其后的错误下面
Enter seat number:
Enter seat number: 5
Enter customer name: charles
Unhandled Exception: System.FormatException: Input string was not in a correct format.
at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer & number, NumberFormatInfo info, Boolean parseDecimal).....
错误消息是相当漫长的,将已经张贴图片,但我没有足够的声誉这样做还..
哪有我在我的bookSeat函数中成功实现锁定并在运行时在多个线程中调用它?
此错误有无关锁定。当您尝试将字符串转换为数字时产生。 –
如果仔细观察堆栈跟踪,您会发现代码中的哪个位置会最终引发调用。 – Richard
它只是我还是这种“错误的建筑”?认为使用函数式编程思想的一部分是为了避免这样的问题... 只是放弃锁定并使用代理/邮箱的某些变体,会不会更好?那么应用“先到先得”,并且因为只有一个人在任何时候访问该列表,所以不需要锁定。 –