multithreading - 在 STM TVar 中使用整数是个好主意吗?

标签 multithreading haskell

我有一个函数a f,它返回一个大整数。接近结束时,程序必须将 f 的所有返回值相加。该计算机的物理内存太有限,无法存储 f 的所有返回值。所以我需要将其放入文件缓冲区中。 TVar 能够处理整数吗?有没有一种解决方案可以抛出 f 的所有返回值?另外,单独的线程可以同时读取它并缓冲它吗?

最佳答案

你的问题不太清楚。据我了解,您需要存储函数 f 在程序运行期间返回的所有结果,并且由于存在大量此类结果,您希望将这些结果存储在文件中。由于在计算后立即实际存储每个结果的效率很低,因此您希望实现某种形式的缓冲。

如果是这种情况,您可以使用类似 Chan 的内容例如,这是一个无界阻塞 FIFO 队列。为了回答您的问题之一,该结构是专门为多线程并发访问而设计的。

因此,您可以在调用 f 的地方运行主程序,并且对于每次调用,您还可以将结果插入 Chan.您还可以生成另一个线程,该线程将连续从 Chan 读取并将结果写入文件中。

现在,如果主线程(调用 f 的线程)的速率远高于另一个线程将结果存储在磁盘上的速率,那么您将回到原来的问题,其中结果堆积在陈和你在某些时候仍然会被遗忘。对于这种特殊情况,您可以使用类似 BoundedChan 的内容。与 Chan 类似,但当 channel 已满时会在插入时阻塞。在这种情况下,主线程有时可能必须等待写入线程将结果存储到磁盘上,但您可以保证永远不会用 f 的许多结果填满内存。

我们实际上可以为此构建一个很好的抽象。我们可以想象一个函数traceable,给定一个函数 f 和一种存储值的方法,它给我们一个返回与 f 相同结果的函数,但作为副作用,它还存储结果以供以后分析。

traceable :: (a -> b) -> (b -> IO ()) -> (a -> IO b)
traceable f store = \x -> do
    let result = f x
    store result
    return result

就您而言,程序可能如下所示:

f :: Int -> Int
f = ... -- implementation of f here

main = do
    ch <- newChan
    traceableF = traceable f (writeChan ch)
    forkIO $ resultWriter ch
    -- the main program which calls traceableF here ...

resultWriter :: Chan Int -> IO ()
resultWriter ch = do
    f <- obtainFileHandler
    forever $ do
        result <- readChan
        writeToFile f result

您可能还需要编写一些逻辑,以便主线程等待 resultWriter 线程完成写入磁盘,但基本上就是这样。

希望这能回答您的问题。

关于multithreading - 在 STM TVar 中使用整数是个好主意吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12907212/

相关文章:

.net - 基于程序描述的多线程推荐

Java Swing - 从多线程更新 View

haskell - 无法推导出父类(super class)

haskell - 为什么表达式 `foldr (mappend . Sum) 1 [2]` 会进行类型检查?

haskell - 如何在不使用-XUndecidableInstances的情况下解决功能依赖项的覆盖条件

javascript - 如何在nodejs中的单独线程上执行dos命令?

java - 关于java中使用阻塞队列方法的生产者和消费者模式

mysql - 如何在mysql中更新查询之前插入?

haskell - 对于缺乏类型类回溯的情况,是否有解决方法?

haskell - 是否有类型为 : (Floating a, RealFrac b) => a -> b 的标准 Haskell 函数?