1

我试图说服自己,clojure 确实比 java 更容易进行并发编程。

但我觉得 Clojure Refs/do-sync 与 java“同步”块几乎完全一样。然后我读了这个线程:Clojure STM (dosync) x Java 同步块

--- 我正在重新启动一个新线程,因为如果我在旧线程中发表评论,由于年龄较大,响应可能不高。

Michał Marczyk 在该线程中的第一条评论声称不同之处在于 java 同步块使用锁,而 Clojure 使用事务。我认为这种说法并没有触及问题的本质:在底层,事务仍然是通过锁来实现的。所以“java 使用锁”并不是 Clojure 更好的原因。

我认为真正的好处是 Clojure 事务自动管理锁,就像 DB 事务一样。这样,获取锁的顺序和执行事务的顺序由事务管理器决定,程序员不需要关心这些,而在java世界中,程序员必须显式选择使用哪个锁同步块,这会导致可能的死锁。例如,事务管理器可以使用两阶段锁定来避免死锁。

以上有意义吗?

谢谢杨

4

2 回答 2

6

Clojure 中的 Ref 是一种不同的并发抽象,它像数据库事务一样工作——它具有原子性、一致性和隔离性属性。它建立在 JVM 锁定机制之上,因此可以在 Java 中自己实现。我们不这样做的原因是类似 Ref 的机制需要预先实现其他重要的机制:

于 2013-04-17T20:19:27.580 回答
5

此处引用答案的作者-让我尝试详细说明:

实际上,在引用的答案中,我首先声称“dosyncsynchronized允许访问完全不同的并发抽象”。此外,我synchronized不仅将其描述为“使用锁”,还描述为“一种获取和释放锁的方式”。

换句话说,虽然 STM 确实在后台使用了锁,但它暴露了事务语义,可以这样推断;例如,它通过构造没有死锁(然而,活锁是可能的)。相比之下,synchronized程序员明确地声明在大括号标记的点处获取和释放某某对象的监视器是一种明确的方式。这里的重要区别在于语义,而不是实现。

此外,STM 不仅仅是管理锁定顺序;有 MVCC,正如 Grzegorz 所提到的,有自动重启事务,有ensurecommute(控制一致性与并发权衡,如果你愿意的话),有 STM 和代理之间的合作(代理操作放在队列中,send只有在提交时调度如果从事务中调用时间)。

因此,STM 确实是一种管理锁的机制,这样描述它是有用的;但更大的图景是 STM 实现使用它需要的任何内部细节,包括锁,为程序员提供另一种并发抽象,合理地无泄漏,如果要从中提取全部好处,最终必须这样处理它。

于 2013-04-17T21:19:09.650 回答