在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中复制事务死锁?
答案 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事务......直到达到最大重试次数并引发异常。