在并发 Haskell 中原子地修改多个 IORef

问题描述 投票:0回答:1

atomicModifyIORef的文档说明如下:

此函数对于在多线程程序中安全地使用 IORef 非常有用。如果您只有一个 IORef,那么使用atomicModifyIORef 访问和修改它可以防止竞争条件。

将原子性扩展到多个 IORef 是有问题的,因此建议如果您需要做更复杂的事情,那么使用 MVar 是一个好主意。

我不确定这到底是什么意思。假设我有两个完全独立的 IORef,原子性不能得到保证吗? 如果是这样的话,

atomicModifyIORef

还有什么意义呢?使用起来好像很危险...

现在我知道了STM,但是对于我需要的CAS(比较和交换)实现,它显然运行得更慢。事实上,这篇

文章说,p。 5

在性能方面,CAS的atomicModifyIORef版本要优越得多 到CAS的STM编码。

所以我的问题如下:

    在多线程环境中使用
  1. atomicModifyIORef
     多个 
    IORefs
     时,原子性到底何时被破坏?
  2. 为什么将原子性扩展到多个 IORef 是“有问题的”?有关于该主题的任何参考吗?
multithreading performance haskell concurrency ioref
1个回答
0
投票
IORef 的修改体现了先读后写。因此,如果您像这样编写一个简单的修改实现:

do old <- readIORef myVar writeIORef myVar $ f old
如果两个线程同时执行此代码,则存在潜在的竞争条件。

atomicallyModifyIORef

保证以原子方式执行此操作,因此第一个线程将在第二个线程开始之前完成更新。

但是,如果您有两个 IORef,则不能这样做。假设您想要将某个值从一个值传输到另一个值,您可以原子地递减一个值,然后原子地递增另一个值,但是在这两个操作之间有一个总和在传输过程中的时间段,因此状态不一致。

将原子性扩展到多个 IORef 需要大量额外的开销来跟踪事务中包含哪些 IORef、存储回滚情况下的值等。即使没有完成原子事务,这也会为 IORef 的任何使用付出代价。所以这是一个坏主意。这就是 TRef 的用途。

© www.soinside.com 2019 - 2024. All rights reserved.