如何在多个线程中实现函数内锁定f# [英] how to implement locking within function in multiple threads f#

查看:70
本文介绍了如何在多个线程中实现函数内锁定f#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个可变的列表,称为票证,其中包含票证类型. 我还有一个bookSeat函数,它模仿预订座位.由于F#列表类型是不可变的,所以我的bookSeat函数总是返回新的,修改过的票证列表副本.

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

我现在想创建两个都调用bookSeat的线程,并且我想在bookSeat内实现锁定以避免竞争状态.

I now want to create two threads that both invoke bookSeat and i want to implement locking within bookSeat to avoid a race condition.

我想出了这个新的bookSeat函数(对于编程和f#还是很新的,代码可能看起来非常菜鸟)

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..

我如何在我的bookSeat函数中成功实现锁定并在运行时在多个线程中调用它?

How can i successfully implement locking within my bookSeat function and invoke it within multiple threads at run time?

推荐答案

您的两个线程正在争夺控制台.输入查尔斯"很可能被执行seatNo := int(Console.ReadLine()分配的线程消耗了.

Your two threads are competing for the console; likely the input "charles" was consumed by a thread executing the seatNo := int(Console.ReadLine() assignment.

我同意有关使用Agents/MailboxProcessors的评论,但是如果要使用锁来锁定它,请锁定提示输入序列:

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()
  )
  ...

这篇关于如何在多个线程中实现函数内锁定f#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆