我试图说服自己,对于并发编程来说,clojure确实比java更容易。
但我觉得Clojure Refs / do-sync几乎与java“synchronized”块完全相同。然后我读了这个帖子:Clojure STM ( dosync ) x Java synchronize block
---我正在重新启动一个新线程,因为如果我在旧帖子中发表评论,由于年龄的原因,回复可能不会很高。
MichałMarczyk在该主题中的第一条评论声称差异是java同步块在Clojure使用事务时使用锁。我认为这个说法没有触及问题的本质:在底部,交易仍然由锁实现。所以“java using locks”并不是Clojure更好的原因。
我认为真正的好处是Clojure事务自动管理锁,就像数据库事务一样。这样,获取锁的顺序和发生事务的顺序由事务管理器决定,因此程序员不需要关心它,而在java世界中,程序员必须明确选择要使用的锁。同步块,导致可能的死锁。例如,事务管理器可以使用两阶段锁定来避免死锁。
以上是否有意义?
感谢 杨
答案 0 :(得分:6)
Ref in Clojure是一种不同的并发抽象,它的工作方式类似于数据库事务 - 它具有Atomicity,Consistency和Isolation属性。它建立在JVM锁定机制之上,因此可以在Java中自己实现它。我们不这样做的原因是Ref like机制需要事先实现其他非平凡的机制:
答案 1 :(得分:5)
这里引用答案的作者 - 让我试着详细说明:
实际上,我在引用的答案中声称,首先,“dosync
和synchronized
可以访问完全不同的并发抽象”。此外,我将synchronized
描述为“使用锁”,而不是“获取和释放锁定的方式”。
换句话说,虽然STM当然使用引擎盖下的锁,但它暴露了事务性语义,这可以被理解;例如,它没有构造的死锁(但是,活锁是可能的)。相比之下,synchronized
显然不过是程序员声明要在大括号标记的点处获取和释放此类对象的监视器的方式。这里的重要区别是语义,而不是实现。
此外,STM比管理锁定顺序还要多;正如Grzegorz所提到的那样MVCC会自动重启事务,有ensure
和commute
(控制一致性与并发性权衡,如果你愿意),STM和Agent之间的合作(代理行为)使用send
放入队列只有在事务中调用时才会在提交时调度。
因此,STM确实是一种管理锁的机制,因此将其描述为有用;但更大的情况是,STM实现使用它需要的任何内部细节,包括锁,为程序员提供另一种并发抽象,合理的非漏洞,如果要从中获取全部收益,最终必须接受这种抽象。它