是否可以在Clojure中复制事务死锁?

时间:2015-02-11 11:22:14

标签: clojure transactions deadlock

在SQL中,复制事务死锁相对容易。

==SESSION1==
begin tran
update table1 set ... where ...
[hold off further action - begin on next session]

==SESSION2==
begin 
update table1 set ... where ...
[hold off further action - begin on next session]

==SESSION3==
<list blocked transactions - see session2>

现在有了Clojure交易 - 你不能打开它们并让它们打开,s表达式不允许你这样做。

所以我对上面的情景感到好奇。

我的问题是:是否可以在Clojure中复制事务死锁?

2 个答案:

答案 0 :(得分:0)

根据Rich Hickey的说法:

  

Clojure的STM和代理机制无死锁。它们不是具有阻塞选择性接收的消息传递系统。 STM在内部使用锁,但会自动执行锁冲突检测和解决。

更多详情可在this群组中找到。

答案 1 :(得分:0)

Clojure中的STM旨在为refs 提供原子,一致和隔离的操作,而无需锁定。为了实现这一点,我们实现了一些功能,如refs documentation中所述,但其中一个要点是要有一个乐观的&#34;策略,处理每个事务的数据版本,并在写入时比较此版本和ref版本。

这种乐观策略也可以在数据库中实现,例如在Oracle

无论如何,在Clojure中,如果你真的想要创建一个死锁,你将不得不使用低级别的机制,例如明确在对象上创建锁的locking宏(与{{1}相同)在Java中)并明确管理对共享资源的访问。

编辑: livelock 的示例 这个例子来自 Clojure Programming ,@ cgrand和al。

synchronized

事务A在repl线程中执行。事务B将在一个单独的线程中执行,但由于(let [retry-count (agent 0) x (ref 0)] (try (dosync ;; transaction A @(future (dosync ;; transaction B (send-off retry-count inc) (ref-set x 1))) (ref-set x 2)) (catch Exception e (println (str "caught exception: " (.getMessage e)))) (finally (await retry-count))) [@x @retry-count]) caught exception: Transaction failed after reaching retry limit [1 10000] user> 在A中是deref,它会阻塞直到B结束。当A尝试future时,x已经被B修改,这会触发A的重试,这会产生新的线程和B事务......直到达到最大重试次数并引发异常。