2016-03-31 48 views
2

当我们运行一个STM表达式时,线程被阻塞,并且如果条目被修改,则事务再次运行一次。Haskell STM并重试

但我想知道:

  • 如果我们读它,在特定分支通往重试,实际上并没有使用STM变量,将更新它尝试重新进行交易?

  • 线程被阻塞时,它是否真的被阻塞?还是在线程池中回收以供其他可能的等待操作使用?

+1

我努力遵循你的第一个问题。如何提供一个例子?至于你的第二个问题:线程被阻塞。然而Haskell线程实际上是默认的绿色线程,所以很多都在一个系统线程中运行。这意味着其他Haskell线程在阻塞时仍然可以工作。 –

+0

对于第一个问题:如果读取2个变量,但我的交易实际上取决于值1 – nicolas

+0

我看到..我想绿色线程是否足够有效以至于不能真正在意第一个近似的实现 – nicolas

回答

5
  1. 是的。读取STM变量将调用stmReadTVar - 请参阅here。这将在事务记录中生成新条目,并在提交时进行检查。如果你看看here,你会发现ReadTVarOp被标记为带有副作用的操作(has_side_effects = True),所以我不认为编译器会消除它,无论你使用它的结果与否。
  2. 正如@WillSewell所写,Haskell使用绿色线程。您甚至可以在单线程运行时使用STM,而不用担心实际的OS线程会被阻塞。
+0

感谢您的来源 – nicolas

2

Re。 1:根据我的理解你的问题,是的,这是正确的;您的整个STM交易将具有世界一致的视图,包括分支由orElse组成(请参阅:https://ghc.haskell.org/trac/ghc/ticket/8680)。但我不确定你的意思,“但我的交易实际上取决于只有一个变量的价值”;如果你做了一个readTVar,那么对该变种的更改将被跟踪。

Re。 2:你可以将绿色线程看作是保存的计算状态的块,它们存储在类似堆栈的东西中,然后弹出,运行一段时间,并在他们无法进一步取得进展时放回堆栈(“封锁”)或足够长的时间后。并行发生的程度取决于您要求运行时使用的操作系统线程数(通过+RTS -N)。你可以有一个使用数千个绿色线程的并发程序,但只能在一个操作系统线程中运行,这很好。

+0

有趣,谢谢 – nicolas