2

我是 Haskell 的新手,我不知道我对 Haskell wiki 上的这个例子有什么不理解:http ://www.haskell.org/haskellwiki/Implement_a_chat_server

有问题的具体代码是这样的:

runConn :: (Socket, SockAddr) -> Chan Msg -> -> IO ()
runConn (sock, _) chan = do
    let broadcast msg = writeChan chan msg
    hdl <- socketToHandle sock ReadWriteMode
    hSetBuffering hdl NoBuffering
    chan' <- dupChan chan
    -- fork off thread for reading from the duplicated channel
    forkIO $ fix $ \loop -> do
        line <- readChan chan'
        hPutStrLn hdl line
        loop
    -- read lines from socket and echo them back to the user
    fix $ \loop -> do
        line <- liftM init (hGetLine hdl) 
        broadcast line
        loop

hdl上面的代码有一个线程同时(可能)写入句柄,因为另一个线程正在读取它。这安全吗?

我怀疑forkIO(Haskell 内部而不是系统线程库或进程)的性质是使它工作的原因,但我不确定。

我检查了forkIO的文档中是否提到了 IO 句柄,但一无所获。我还检查了System.IO的文档,但找不到任何提及在不使用锁定的情况下在线程之间使用句柄的内容。

那么,当文档没有提到任何关于线程安全的内容时,有人可以告诉我如何知道这样的事情何时是安全的吗?

4

2 回答 2

3

不是它的性质forkIO使它起作用,而是它的性质MVar用于实现ChanHandle.

如果您想了解其Chan工作原理,请查看Simon Marlow的优秀书籍“Haskell 中的并行和并发编程”的第 7 章中的“MVar 作为构建块:无界通道”部分。在同一章中,有一个关于和的部分将帮助您了解如何以线程安全的方式实现。forkIOMVarHandle

第 12 章专门讨论了实现网络服务器的各种方法,包括使用 STM 而不是Chans 实现的聊天服务器。

于 2013-10-26T06:12:09.727 回答
0

如果它不安全,阻塞套接字几乎是不可能使用的。如果您的协议是异步的并且您正在使用阻塞套接字,那么您几乎一直需要一个线程阻塞读取。如果您随后需要向另一方发送消息,您该怎么做?等对方给你发消息?

于 2013-10-26T04:58:26.757 回答