Phi*_*sky 6 haskell stm unsafe-perform-io
在这个伪代码块中:
atomically $ do
if valueInLocalStorage key
then readValueFromLocalStorage key
else do
value <- unsafeIOToSTM $ fetchValueFromDatabase key
writeValueToLocalStorage key value
Run Code Online (Sandbox Code Playgroud)
使用安全unsafeIOToSTM吗?文档说:
STM实现通常会多次运行事务,因此如果您的IO有任何副作用,您需要为此做好准备.
基本上,如果事务失败,那是因为某个其他线程,wroteValueToLocalStorage并且当重试事务时,它将返回存储的值,而不是再次从数据库中获取.
STM实现将中止已知无效且需要重新启动的事务.这可能发生在unsafeIOToSTM的中间,因此请确保您没有获取任何需要释放的资源(在中止事务时忽略异常处理程序).例如,这包括使用Handles执行任何IO.出错可能会导致随机死锁.
这让我很担心.从逻辑上讲,如果fetchValueFromDatabase没有打开新连接(即使用现有连接),一切都应该没问题.我还缺少其他陷阱吗?
当IO运行时,事务可能已经看到不一致的内存视图.由于事务的实现方式,在整个程序中您期望为真的不变量在事务中可能不正确.通常这对程序员来说是不可见的,但是使用unsafeIOToSTM可以暴露它.
key 是单个值,没有不变量可以打破.
我建议从 STM 事务中执行 I/O 是一个坏主意。
想必您想要的是避免两个线程同时进行数据库查找。我要做的是这样的:
查看该项目是否已在缓存中。如果是的话,我们就完成了。
如果不是,则用“我正在获取此”标志对其进行标记,提交 STM 事务,从数据库中获取它,然后执行第二个 STM 事务将其插入到缓存中(并删除该标志)。
如果该项目已被标记,retry则交易。这会阻塞调用线程,直到第一个线程插入数据库中的值。