是否可以在 Clojure 中复制事务死锁?
Is it possible to replicate a transaction deadlock in Clojure?
在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 中复制事务死锁?
根据 Rich Hickey 的说法:
Clojure's STM and agent mechanisms are deadlock-free. They are not message-passing systems with blocking selective receive. The STM uses locks internally, but does lock-conflict detection and resolution automatically.
可以在this组中找到更多详细信息。
Clojure 中的 STM 旨在提供对引用的原子、一致和隔离的操作,没有 锁定。如 refs documentation 中所述,为实现此目的实施了多项功能,但要点之一是拥有一个 "optimistic" 策略,该策略处理每个事务的数据版本并将此版本与 ref 进行比较编写时的版本。
这种乐观策略也可以在数据库中实现,例如在 Oracle.
无论如何,在 Clojure 中,如果你真的想创建一个死锁,你将不得不使用低级机制,例如 locking
宏,它显式地在一个对象上创建一个锁(与 synchronized
in Java) 并显式管理对共享资源的访问。
编辑:活锁示例
此示例来自 Clojure Programming、@cgrand 和 al。
(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在repl线程中执行。事务 B 将在单独的线程中执行,但由于 future
在 A 中被取消引用,因此它会阻塞直到 B 完成。当 A 尝试 (ref-set x 2)
时,x 已被 B 修改,这会触发 A 的重试,从而产生新的线程和 B 事务……直到达到最大重试次数并引发异常。
在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 中复制事务死锁?
根据 Rich Hickey 的说法:
Clojure's STM and agent mechanisms are deadlock-free. They are not message-passing systems with blocking selective receive. The STM uses locks internally, but does lock-conflict detection and resolution automatically.
可以在this组中找到更多详细信息。
Clojure 中的 STM 旨在提供对引用的原子、一致和隔离的操作,没有 锁定。如 refs documentation 中所述,为实现此目的实施了多项功能,但要点之一是拥有一个 "optimistic" 策略,该策略处理每个事务的数据版本并将此版本与 ref 进行比较编写时的版本。
这种乐观策略也可以在数据库中实现,例如在 Oracle.
无论如何,在 Clojure 中,如果你真的想创建一个死锁,你将不得不使用低级机制,例如 locking
宏,它显式地在一个对象上创建一个锁(与 synchronized
in Java) 并显式管理对共享资源的访问。
编辑:活锁示例 此示例来自 Clojure Programming、@cgrand 和 al。
(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在repl线程中执行。事务 B 将在单独的线程中执行,但由于 future
在 A 中被取消引用,因此它会阻塞直到 B 完成。当 A 尝试 (ref-set x 2)
时,x 已被 B 修改,这会触发 A 的重试,从而产生新的线程和 B 事务……直到达到最大重试次数并引发异常。