【问题标题】:Haskell concurrency and HandlesHaskell 并发和句柄
【发布时间】:2024-01-19 21:21:01
【问题描述】:

我正在编写一个小通知服务器来将数据推送到客户端。基本架构看起来像这样(精简伪代码):

acceptConnections sock = forever $ do
    connection <- accept sock
    forkIO (handleConnection connection)

handleConnection connection = do
    connectionHandle <- socketToHandle connection ReadWriteMode
    handleMessage connectionHandle
    hClose connectionHandle

handleMessage connectionHandle = forever $ do
    message <- hGetLine connectionHandle 
    if shouldPushMessage message
        then hPutStrLn targetConnection message
        else return () 

其中targetConnection(在handleMessage中)来自一个单独的连接,并且在另一个线程中挂起handleMessage,等待其缓冲区被填充。我认为这会导致问题,因为我有 2 个线程访问同一个句柄。所以,我的问题是,为什么这不是问题?还是它,我只是还没有看到它变成一个问题?在我的实际应用程序中,当我抓取 targetConnection 时,我是通过我通过 MVar 访问的地图来执行此操作的,但在 hGetLine 调用中并没有安全地访问它。

免责声明:我是一个完整的 Haskell 和多线程新手

感谢您的任何解释/见解!

【问题讨论】:

    标签: haskell concurrency handle


    【解决方案1】:

    Handleimplemented in GHC 一样,已经是一个封装在底层 IODevice 上的 MVar。我不太明白你在做什么(不是说不清楚,我有点病,所以也许我很慢)但我猜在 Handle 的线程安全处理中内置的 GHC 正在拯救你。

    【讨论】:

    • 别担心,我确信我没有做最好的工作来说明我在做什么——基本上我很好奇 hPutStrLn 和 hGetLine 是如何被不同线程“同时”调用的同一个句柄。你回答了我笨拙的问题。谢谢!