how to implement locking within function in multiple threads f#

天大地大妈咪最大 提交于 2019-12-13 05:04:55

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!