2024 年 Clojure 状态调查中分享您的想法!

欢迎!请查看 关于 页面,了解此服务的更多信息。

+6
Clojure

我们遇到了这个问题很频繁,因为我们现在大量使用 Clojure 来提升一个系统的规模,我猜数字只是 与我们作对,但不管怎样,这阻碍了在多线程环境中使用 Clojure。我已准备了一个 最小化 示例 来重现该问题。因此,问题是,

  • 是否有解决此问题的方法?(类似某些动态变量,我没有找到,但可能存在)
  • 为什么这被认为是“重型锤子”?(也就是说,require 并不经常使用,大多在单线程环境(如 repl)中,而大多数生产环境将从这中受益)
  • 有何提示说明为什么会发生这种情况?(从源代码中,我并不完全理解为什么会发生这种情况,可能是某些 ns 需求(因此添加了 ns)添加了所有符号,而在那里,另一个线程在需要时替换了那个 ns)

1 个答案

+2

存在一个私有的函数 serialized-require,该函数在执行 require 之前简单地获取一个全局锁,你可以使用它,或者在你的 Java 代码中围着 clojure.core/require 的任何使用操作进行相同的事情,即通过在单个对象上的同步方法中创建所有 require 调用来获取全局锁。

感谢你的回答,我知道这一点,但是这在我们的情况中是不可能实现的 `:(`,因为至少有一个这些类是 AOT 编译的,它反过来使用 `loadWithClass`,它反过来调用 `require`(以加载 `clj` 文件),这是我们无法控制的。
如果你无法更改那段 AOT 编译的代码,因为它确实不在你的控制之下,那么你在系统启动时确保在某些代码(如以下所示)在多个线程从多个线程中调用 require 之前被评估,这是否在你的控制之下?当然,println 是可选的。


(def original-require clojure.core/require)

(defn my-serialized-require [& args]
  (locking clojure.lang.RT/REQUIRE_LOCK)
    (println "my-serialized-require acquired the lock...")
    (apply original-require args)
    (println "my-serialized-require releasing lock...")))

(alter-var-root #'clojure.core/require (fn [& args] my-serialized-require))


如果这对你来说不可能,你允许编译 Clojure 源代码的修改版本并在你的项目中使用它吗?如果可以,你可以修改 `require` 的定义以使其为锁定版本。
就其本身而言,requiring-resolve 是线程安全(锁定)的公共 API,我的理解是计划在某个时候(可能是 Clojure 1.11?Alex 可能对此有一些见解)使常规的 require 使用此机制变得线程安全,但在将此类更改应用到 Clojure 的基本部分之前,仍需要进行一些分析和可能的研究。
再次感谢,现在我终于明白问题所在,我认为可以针对我们的情况制定一个解决方案,但这并不能解决根本问题,我非常期待看到一个长期的、通用的解决方案。
再次感谢,现在我终于明白问题所在,我认为可以针对我们的情况制定一个解决方案,但这并不能解决根本问题,我非常期待看到一个长期的、通用的解决方案。
我理解你希望有一个长期的通用解决方案。我是一个感兴趣的志愿者,正在回应你询问解决方案的部分。我对Clojure发布版本的內容没有控制权。官方的Clojure维护者也在阅读这些问题,他们可以提供他们认为的长期通用解决方案。
非常感谢你所做的一切,谢谢!
您好,我只是在上文中回声一些内容——是的,这是一个已知问题,并且已列入Clojure 1.11的候选清单中。并行(冲突)加载相对较少。`requiring-resolve`是在1.10中添加的,用于覆盖最常见的动态加载使用场景(这很容易发生竞争)。

正如Andy上面提到的,clojure.lang.RT/REQUIRE_LOCK有意保留,以便用户程序可以参与这个锁。这应该仍然被视为实现,并可能在未来被移除,但在此期间,可以像你提到的那样使用建议的解决方案。

预期长期解决方案是使常规`require`更安全,但这需要进行大量的分析和测试,而这些测试尚未完成。
gen-class可能是另一个常见用例。如果您从Clojure生成一个类,并且Java在多个线程中创建该类的实例,则生成的类初始化器很可能会以非线程安全的方式在内部要求实现Clojure命名空间。我们目前似乎存在这样的问题。
...