我知道,将带有副作用的函数放在STM事务中通常是一种不好的做法,因为它们可能会被重试和多次调用。

但是在我看来,您可以使用代理来确保仅在事务成功完成之后才执行副作用。

例如

(dosync
  // transactional stuff
  (send some-agent #(function-with-side-effects params))
  // more transactional stuff
  )

这是好习惯吗?

优点/缺点/陷阱是什么?

最佳答案

原始:

似乎这样对我有用。根据您的副作用,您可能要使用发送(对于IO绑定(bind)的操作)而不是发送(对于cpu绑定(bind)的操作)。发送/发送将把任务排队到内部代理执行程序池中的一个(对于cpu有一个固定大小的池,对于io ops有一个无限制的大小池)。任务入队后,工作不在dosync的线程中,因此此时您已断开连接。

当然,您需要从事务内捕获所需的任何值到已发送的函数中。而且您需要处理由于重试而可能多次发生的发送。

更新(请参阅评论):

引用事务中的代理发送将被保留,直到引用事务成功完成并执行一次。因此,在我上面的回答中,发送不会多次发生,但是不会在ref事务期间发生,这可能不是您想要的(如果您希望记录日志或执行副作用)。

关于concurrency - 使用代理来完成STM交易中的副作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4768592/

10-17 00:26