英文:
modifyMVar: where does it allow another writer to "enter"?
问题
这是modifyMVar_
函数的代码。注释中说它允许多个写操作者,并且如果发生异常,它会替换原始内容。我对代码的执行位置不是100%确定。
-
在哪里允许其他写操作者修改内容? 我只看到一种可能性:如果
putMVar
不是原子的(显然不是),并且另一个线程更快地放入自己的内容,那么这可能发生在哪里? -
在异常发生时在哪里替换原始内容?我看到
restore
返回取出的a
值。他们是否意味着在putMVar
期间再次出现多个写操作者,但现在在“异常处理程序”中? -
我可以将
modifyMVar
用作同步代码块吗?类似于Java或Python中的互斥体(mutex)?似乎是可以的,但与其他语言中的标准锁/互斥体相比可能会有什么问题?我认为io
参数在执行时是互斥的,就像标准锁一样,是吗?
{-|
这是一个对修改'MVar'内容的异常安全包装器。
与'withMVar'类似,如果在操作过程中引发异常,'modifyMVar'将替换'MVar'的原始内容。
只有当没有其他生产者为此'MVar'时,此函数才是原子的。
换句话说,它不能保证在'modifyMVar_'有机会写入MVar之前,MVar的值是否已经被另一个线程的写操作修改。
-}
{-# INLINE modifyMVar_ #-}
modifyMVar_ :: MVar a -> (a -> IO a) -> IO ()
modifyMVar_ m io =
mask $ \restore -> do
a <- takeMVar m
a' <- restore (io a) `onException` putMVar m a
putMVar m a'
英文:
This is the code of modifyMVar_
. The comment says it allows multiple writers. And that it replaces the original content if an exception happens. I am not 100% sure about my understanding where it happens looking at the code.
- where does it allow another writer to alter the content? I see only one possibility: if
putMVar
is not atomic (obviously it is not) and another thread puts its own content faster. Is it the place? - where does it replace the original content on exception? I see that
restore
returns takena
value back. Do they mean again possibility of multiple writers duringputMVar
but now in the "exception handler"? - Can I use
modifyMVar
as a synchronized code block? Like a mutex in Java or in Python? It seems yes, but what could be a problem in comparison with a standard lock/mutex in other languages? I think theio
argument is executed mutually exclusive as in a standard lock, is not it?
{-|
An exception-safe wrapper for modifying the contents of an 'MVar'.
Like 'withMVar', 'modifyMVar' will replace the original contents of
the 'MVar' if an exception is raised during the operation. This
function is only atomic if there are no other producers for this
'MVar'. In other words, it cannot guarantee that, by the time
'modifyMVar_' gets the chance to write to the MVar, the value
of the MVar has not been altered by a write operation from another thread.
-}
{-# INLINE modifyMVar_ #-}
modifyMVar_ :: MVar a -> (a -> IO a) -> IO ()
modifyMVar_ m io =
mask $ \restore -> do
a <- takeMVar m
a' <- restore (io a) `onException` putMVar m a
putMVar m a'
答案1
得分: 3
-
这部分文档允许其他编写者修改内容的位置是:
modifyMVar_
的理念是,如果有多个并发的modifyMVar_
,其中一个将运行其takeMVar
,现在MVar
为空,所以所有其他modifyMVar_
将在takeMVar
上阻塞。这保证了对相同变量的modifyMVar_
将按顺序运行,因此是原子的。- 如果另一个线程直接使用
putMVar
(而不是通过modifyMVar_
间接使用),这将解锁等待的modifyMVar_
,从而破坏了原子性保证。
-
它在异常情况下替换原始内容的位置是:
action `onException` putMVar m a
运行action
,如果它引发异常,在重新引发异常之前会运行putMVar m a
。
-
我可以将
modifyMVar
用作同步的代码块吗?- 是的,
MVar ()
是一个互斥锁。
- 是的,
英文:
> 1. where does it allow another writer to alter the content?
I assume you are referring to this part of the documentation:
> This function is only atomic if there are no other producers for this MVar
.
The idea behind modifyMVar_
is that if there are multiple concurrent modifyMVar_
, one of them will run its takeMVar
, and now the MVar
is empty so all the other modifyMVar_
will block on takeMVar
. This guarantees that modifyMVar_
(on the same variable) will run sequentially, and therefore atomically.
If another thread uses putMVar
directly (instead of indirectly via modifyMVar_
), that will unlock a waiting modifyMVar_
, which breaks the atomicity guarantee.
> 2. where does it replace the original content on exception?
action `onException` putMVar m a
runs action
and if it raises an exceptions, runs putMVar m a
before re-raising the exception.
> 3. Can I use modifyMVar as a synchronized code block?
Yes, an MVar ()
is a mutex.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论