haskell - Haskell 中的并发文件读/写?

标签 haskell file-io concurrency

我有一个大文件,用于存储二进制数据。有多个线程读取和写入这些文件,我当前的设计使用单个Lock 来同步它们。这样,我在 ReadWriteMode 中只为一个文件打开一个 Handle,并且所有线程在想要执行某些 I/O 时都会争夺该单个锁。

我想通过允许多个读者同时工作来改进这一点。我尝试的是使用 RWLock并打开多个句柄。 RWLock 将确保只有一个线程修改文件,而允许多个线程(与我打开的句柄一样多,一个编译时常量)同时读取。当尝试运行它时,我对运行时 allows only one 的事实感到震惊。 ReadWriteMode 中的Handle 使文件随时存在。

我该如何解决这种情况?我认为获取/释放 Handle 是一项昂贵的操作,因此在获取 RWLock 后仅以适当的模式打开文件并不是真正的选择。或者也许有一个包提供类似于 Java FileChannelread 的 API和 write方法?

PS:我想支持 32 位架构,因此内存映射 IO 对于大于 4GiB 的文件是不可能的,对吗?

最佳答案

您应该围绕文件句柄和互斥锁构建一个类型。这是一个简单的实现,我认为它可以满足您的目的。

module SharedHandle (SharedHandle, newSharedHandle, withSharedHandle) where

import Control.Concurrent.MVar
import System.IO              

data SharedHandle = SharedHandle Handle (MVar ())

newSharedHandle :: IO Handle -> IO SharedHandle
newSharedHandle makeHandle = do
    handle <- makeHandle
    lock <- newMVar()
    return $ SharedHandle handle lock

withSharedHandle :: SharedHandle -> (Handle -> IO a) -> IO a
withSharedHandle (SharedHandle handle lock) operation = do
    () <- takeMVar lock
    val <- operation handle
    putMVar lock ()
    return val

这里所做的是我创建了一个新的数据类型,它本质上只是一个文件句柄。唯一的区别是它还带有通过 MVar 实现的自己的单独互斥锁。我提供了两个函数来操作这种新类型。 newSharedHandle 接受一个操作,该操作将创建一个普通句柄并创建一个带有新锁的共享句柄。 withSharedHandle 接受一个对句柄进行操作的操作,锁定共享句柄,执行该操作,然后解锁该句柄。请注意,模块中没有提供构造函数或访问器,因此我们可以放心,没有进程会忘记释放锁,并且我们永远不会在某一特定访问上出现死锁。

用这种新类型替换程序中的所有文件句柄可以解决您的问题。

关于haskell - Haskell 中的并发文件读/写?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23395590/

相关文章:

haskell - 如何并行运行一系列独立 IO 操作?

java - 如果您将对象分配给最终字段,其他线程是否会看到该对象的非最终/非 volatile 字段的先前更新?

haskell - 以无序元组为键的映射

haskell - QuickCheck 仅限于某些数据构造函数

macos - 从 GHCi 中的文件加载函数时出错

python - Python 类是否可以编写成可以传递给 write()?

c++ - 将二维数组写入输出文件 - C++

c# - 对比 C# 泛型与 Haskell 参数化类型

java - 线程 "main"java.io.FileNotFoundException : Error 中的异常

mysql - Rails 数据库中并发请求的唯一性处理