Clojure STM ( dosync ) x Java 同步块

2024-02-28

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(使用前将#替换为@)

Clojure STM ( dosync ) x Java 同步块 的相关文章

随机推荐