当 Java 提供并发编程的能力时,使用 Clojure(而不是 Java)的主要优势是什么?
9 回答
Clojure 是为并发而设计的。
Clojure 在比 Java 更高的抽象级别上提供并发原语。其中一些是:
一种软件事务内存系统,用于处理对共享引用的同步和协调更改。您可以将多个引用更改为原子操作,而不必担心程序中的其他线程在做什么。在您的交易中,您将始终拥有一致的世界观。
用于异步更改的代理系统。这类似于 Erlang 中的消息传递。
线程局部更改变量。这些变量有一个根绑定,由程序中的每个线程共享。但是,当您重新绑定变量时,它只会在该线程中可见。
所有这些并发原语都建立在 Clojure 不可变数据结构(即列表、映射、向量等)之上。当您进入可变 Java 对象的世界时,所有的原语都分解了,您又回到了锁和条件变量(必要时也可以在 clojure 中使用)。
如果不是 Clojure 方面的专家,我会说主要优点是 Clojure 隐藏了并发编程的许多细节,众所周知,魔鬼在细节中,所以我认为这是一件好事。
您可能想查看Rick Hickey(Clojure 的创建者)关于 Clojure 并发的精彩演示。编辑:显然 JAOO 已经删除了旧的演示文稿。我还没有找到新的来源。
因为 Clojure 是基于函数式编程范式的,也就是说它通过遵循一些简单的规则来实现并发安全:
- 不可变状态
- 功能没有副作用
这样编写的程序几乎内置了水平可伸缩性,而基于锁的并发机制(如 Java)容易出现涉及竞争条件、死锁等的错误。
因为世界在过去 10 年中取得了进步,而 Java 语言(!= JVM)发现很难跟上。用于 JVM 的更现代的语言基于新思想和改进的概念,这使得许多繁琐的任务变得更加简单和安全。
拥有不可变类型的一个很酷的事情是大多数内置函数已经是多线程的。一个简单的“减少”将跨越多个内核/处理器,无需您进行任何额外的工作。
所以,确定你可以使用 Java 进行多线程,但它涉及锁等等。Clojure 是多线程的,无需任何额外的努力。
除了 Clojure 通过不可变数据、变量、引用(和软件事务内存)、原子和代理实现并发的方法之外……它是一个 Lisp,值得学习。您可以获得 Lisp 宏、解构、第一类函数和闭包、REPL 和动态类型——以及用于列表、向量、映射和集合的文字——所有这些都建立在与 Java 库的互操作性之上(还有一个 CLR 版本也在开发中。 )
它与Scheme或 Common Lisp 并不完全相同,但如果你想了解计算机程序的结构和解释,或者想了解 Paul Graham 在他的文章中所说的内容,学习它会对你有所帮助,你可以从XKCD。;-)
是的,Java 为并发程序提供了所有必要的功能。
一个类比:C 为内存安全程序提供了所有必要的功能,即使有大量的字符串处理。但是在 C 中,内存安全是程序员的问题。
碰巧的是,分析并发性是相当困难的。最好使用固有的安全机制,而不是试图预测所有可能的并发危险。
如果您试图通过添加互锁来使共享内存可变数据结构并发程序安全,那么您就是在走钢丝。另外,它在很大程度上是不可测试的。
一个不错的折衷方案可能是使用 Clojure 的函数式风格编写并发 Java 代码。
这个视频演示提供了一个非常有力的案例,围绕着作为尝试实现的高效持久数据结构。
Java 编程语言的发展相当缓慢,主要是因为 Sun 对向后兼容性的担忧。
为什么不直接使用像 Clojure 和 Scala 这样的 JVM 语言?