问题
I created a mutable list called tickets that contains type Ticket. I also have a bookSeat function that imitates booking a seat.Since F# list type is immutable, my bookSeat function always returns a new, modified, copy of tickets list.
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
I now want to create two threads that both invoke bookSeat and i want to implement locking within bookSeat to avoid a race condition.
I came up with this new bookSeat function (still very new to programming and f#, code might seem very rookie 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)
The code compiles successfully but has an error when i run it. It outputs this followed by an error below
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).....
The error message is quite lengthy, would've posted a picture, but i don't have enough reputation to do so yet..
How can i successfully implement locking within my bookSeat function and invoke it within multiple threads at run time?
回答1:
Your two threads are competing for the console; likely the input "charles" was consumed by a thread executing the seatNo := int(Console.ReadLine()
assignment.
I agree with the comments on using Agents/MailboxProcessors, but if you want to do it with locks, lock the prompt-input sequences:
let bookSeat _ =
lock (seatNo) (fun _ ->
Console.WriteLine("Enter seat number: ")
seatNo := int(Console.ReadLine())
)
lock (name) (fun _ ->
Console.WriteLine("Enter customer name: ")
name:= string(Console.ReadLine().ToString()
)
...
来源:https://stackoverflow.com/questions/30202633/how-to-implement-locking-within-function-in-multiple-threads-f