haskell - Haskell 的 STM `check` 与显式使用 `retry` 不同吗?

标签 haskell stm

我正在通过实现哲学家就餐问题来试验 STM。

无论如何,我有以下定义。

data ChopStick = CS (TVar Bool)

takeChopstick :: ChopStick -> STM ()
takeChopstick (CS chopstick) = do
    isTaken <- readTVar chopstick
    check (isTaken)
    writeTVar chopstick True

这个函数是原子调用的:

atomically $ do
    takeChopstick leftChopstick
    takeChopstick rightChopstick

当使用上面的 takeChopstick 定义运行程序时,我遇到了与使用这个定义运行它不同的结果:

takeChopstick :: ChopStick -> STM ()
takeChopstick (CS chopstick) = do
    isTaken <- readTVar chopstick
    if isTaken
        then retry
        else writeTVar chopstick True

特别是,程序挂起。

check(hackage, stm-2.2.0.1)源码如下:

check :: Bool -> STM a
check b = if b then return undefined else retry

这似乎与我明确使用 retry 的效果相同。

check 与显式使用 retry 有何不同?将 retry 调用进一步向下推会导致它重新启动不同的原子 block 吗?

最佳答案

不,check与使用 retry 没有什么不同明确地说,我只是将参数混淆为 check .

解决方案是checkisTakenFalse ,即 check $ not isTaken .

takeChopstick :: ChopStick -> STM ()
takeChopstick (CS chopstick) = do
    isTaken <- readTVar chopstick
    check (not isTaken)
    writeTVar chopstick True

关于haskell - Haskell 的 STM `check` 与显式使用 `retry` 不同吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31040329/

相关文章:

data-structures - 一个菜鸟函数式程序员关于列表访问的问题

haskell - 使用 HSpec 和 QuickCheck 验证 Data.Monoid 属性

python - 相当于 Haskell 中的 Python urllib

clojure - 可以监控STM的争用级别吗?

Clojure:在一个事务中改变之前通勤导致事务失败

haskell - 无法将类类型与 haskell 中的特定类型匹配

haskell - 从函数返回 GADT

java - Clojure STM ( dosync ) x Java 同步块(synchronized block)

Haskell 代码中充斥着 TVar 操作和函数,带有许多参数 : code smell?

scala - 为什么在抛出异常时 Scala 中的原子 block 会运行两次?