Clojure STM(dosync)方法和Java同步块有什么区别?
我正在阅读“睡觉的理发师”问题中的以下代码。
(http://www.bestinclass.dk/index.clj/2009/09/scala-vs-clojure-round-2-concurrency.html http://www.bestinclass.dk/index.clj/2009/09/scala-vs-clojure-round-2-concurrency.html)
(defn the-shop [a]
(print "[k] entering shop" a)
(dosync
(if (< (count @queue) seats)
(alter queue conj a)
(print "[s] turning away customer" a))))
为了避免竞争条件,dosync
使用,所以我问自己“与Java同步块有什么区别(STM)”?它会阻止这个关键代码吗?
提前致谢 !
丹塔斯
dosync
and synchronized
允许访问完全不同的并发抽象。
synchronized
是一种获取和释放锁的方式。当一个线程进入一个synchronized
块,它尝试获取适当的锁;如果锁当前由不同的线程持有,则当前线程将阻塞并等待它被释放。这会导致某些问题,例如死锁的风险。当线程离开时锁被释放synchronized
block.
dosync
标记要在事务中运行的代码块。 Clojure 中的事务是协调 Refs(使用创建的对象)更改的一种方式ref
功能);如果您需要一些代码来对 Clojure 中的某些可变状态保持一致的视图(并可能更改它们),您可以将它们放入 Refs 中并在事务中执行代码。
事务有一个有趣的属性,如果由于某种原因无法提交,它将重新启动,直到达到一定的最大重试次数(当前硬编码为 10000)。事务无法提交的可能原因之一是无法获得一致的世界观(实际上,相关参考资料 - 有一个“自适应历史记录”设施,这使得这不像看起来那样是一个问题乍一看);其他交易同时进行的更改; ETC。
事务不会有死锁的风险(除非程序员不遗余力地通过 Java 互操作引入与 STM 系统无关的死锁);另一方面,活锁是有一定可能性的,尽管可能性不大。一般来说,很多——尽管不是全部! -- 程序员与数据库事务相关的直觉在 STM 系统(包括 Clojure)的上下文中是有效的。
STM是一个很大的话题; Mark Volkmann 的一本书是学习 Clojure 的 STM 的优秀资源软件事务内存 http://java.ociweb.com/mark/stm/文章。它在最后几节深入讨论了 Clojure 的 STM,但开头部分可以作为很好的入门读物。
至于您引用的代码片段,实际上您通常不想在生产代码中模拟它,因为dosync
块应该几乎总是没有副作用;这print
这里对于演示 STM 的内部工作很有用,但是如果您希望事务在实际代码中产生副作用,您应该让它生成一个 Clojure 代理来达到此目的(只有在事务成功时它才会执行其任务)提交)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)