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

欢迎!有关如何工作的更多信息,请参阅关于页面。

+6
Clojure

我们现在经常遇到这个问题,因为我们现在使用Clojure大规模扩展了系统的一支队伍,我想数字只是在和我们作对,但不管怎样,这阻碍了Clojure在多线程环境中的应用。我已经做出一个最小 示例来重现这个问题。所以,问题来了:

  • 这个问题有没有解决办法?(类似于我们设置的某些动态变量,我没有找到,但可能有的)
  • 为什么这被认为是“重型锤子”?(即通常不进行require操作,通常在单线程环境中(如repl),而大多数生产环境将从中受益)
  • 有什么线索可以解释为什么会发生这种情况?(读取源代码,我并不完全理解为什么会发生这种情况,可能是某个ns的require(因此添加了ns)添加了所有符号,而在那里时,另一个线程在require它时替换了该ns)
有关以下答案的补充:从Java调用require不安全

1 答案

+2

存在一个私有函数 serialized-require,它在执行 require 之前简单地获取全局锁,您可以使用该函数,或者在自己的 Java 代码中对任何使用 clojure.core/require 的地方做相同的事情,即用获取全局锁的方式包装它,例如,通过使所有 require 调用都在一个单一对象的同步方法内部进行。

by
感谢您的回答,我知道这没问题,但这对我们来说不起作用,因为至少有一个类是 AOT 编译的,它使用 `loadWithClass`,而 `loadWithClass` 又会调用 `require`(以加载 `clj` 文件),而我们无法控制这一点。
by
如果您无法更改这些 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` 的定义使其成为带锁版本的。
by
到此为止,require-resolve 是线程安全(带锁的)require 的公共 API,我的理解是计划将来通过这种方式将常规 require 线程安全化(可能是在 Clojure 1.11?Alex 可能在这方面有一些见解)但在这个基本组成部分的改变实现之前,还需要进行一些分析和可能的研究。
再次感谢,现在我明白了问题所在,我认为我可以为我们的情况制定一个解决方案,然而,这并不能解决问题根源,我希望看到对这个问题的长期通用解决方案。
再次感谢,现在我明白了问题所在,我认为我可以为我们的情况制定一个解决方案,然而,这并不能解决问题根源,我希望看到对这个问题的长期通用解决方案。
我理解您对长期通用解决方案的渴望。我是一个感兴趣的志愿者,正在回答您关于解决方案的部分问题。我无法控制Clojure发布版本的内容。官方Clojure维护者也会阅读这些问题,并可以以他们认为长期通用解决方案的方式作出回应。
我对此表示感谢!
by
你好,只是重新表达一下上面的内容——是的,这是一个已知的问题,已列入Clojure 1.11的候选改进列表。并行(冲突)加载相对较少。在1.10版中添加了`requiring-resolve`,以覆盖最常见的动态加载用例(这可能会导致竞争条件)。

如Andy在前所述,clojure.lang.RT/REQUIRE_LOCK故意设置为可用,以便需要这样做且有可能的用户程序可以参与到这个锁中。这仍然应被视为实施细节,并且可能会在未来被删除,但与此同时,你可以使用提到的建议解决方案。

预期长期解决方案是使普通的`require`更安全,但这将需要大量的分析和测试,这些工作尚未完成。
by
gen-class可能是一个另一个常见用例。如果你从Clojure生成一个类,并且Java在多个线程内创建该类的实例,那么生成的类初始化器可能会以非线程安全的方式在内部要求实现的Clojure命名空间。我们似乎现在有这个问题。
...