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

欢迎!请查看 关于 页面以了解该工作的更多信息。

0 投票
 teased potato with glasses next to 3 B core.async

我们遇到了 core.async 中的一个棘手问题

在某些情况下,“不允许超过 1024 个挂起 takes” 在 async-dispatch 线程中引发,尽管实际上只有 1024 个挂起 takes。
以下代码可以迅速触发这种情况

`
(dotimes [_ 5000]
;; - 启动 1024 个线程,它们都在公共通道 (ch) 和单个通道 (x) 上使用 alt!
;; - 公共通道始终保持 '空' 状态
;; - 通过 x 通道唤醒所有线程两次,使它们循环。
;; - 这在 async-dispatch 线程中迅速引发多个 '不允许在单个通道上有超过 1024 个挂起 takes.' 断言。
(let [ch (async/chan)

    threads clojure.core.async.impl.protocols/MAX-QUEUE-SIZE
    wakeups 2
    x-chans
    (mapv (fn [n]
            (let [x (async/chan)]
              (async/go-loop []
                (async/alt!
                  ch nil
                  x ([_] (recur))))
              x))
          (range threads))]
(doseq [x x-chans]
  (dotimes [n wakeups]
    (async/>!! x 42)))
(async/close! ch)))

`

环境
Mac OS,JDK 8,Clojure 1.10.0,core-async 0.6.532

1 答案

0 投票
 person standing near鞠躬 by

尊敬的 Sperber 先生,

我认为我对这个问题并不是很了解。(... 也 ... 实话说,我并没有在这方面花太多心思 :-) ... )

话虽如此,我只是运行了

(ns asyncbug.core
  (:gen-class)
  (:require [clojure.core.async :as async]))


(defn -main
  "I don't do a whole lot ... yet."
  [& args]

  (dotimes [n 5000]
    (comment "
- start 1024 threads that all alt! on a common channel (ch) and
  on an individual channel (x)
- the common channel remains 'empty' all the time
- wakeup all theads twice via the x channel, which makes them loop.
- this quickly raises multiple
  'No more than 1024 pending takes are allowed on a single channel.'
  assertions in an async-dispatch thread.
")
    (let [ch (async/chan)

          threads clojure.core.async.impl.protocols/MAX-QUEUE-SIZE
          wakeups 2
          x-chans
          (mapv (fn [n]
                  (let [x (async/chan)]
                    (async/go-loop []
                      (async/alt!
                        ch nil
                        x ([_] (recur))))
                    x))
                (range threads))]
      (doseq [x x-chans]
        (dotimes [n wakeups]
          (async/>!! x 42)))
      (async/close! ch))

    (println "iteration: " n))

  (println "Hello, World!"))

(defproject asyncbug "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url "https://www.eclipse.org/legal/epl-2.0/"}
  :dependencies [[org.clojure/clojure "1.10.0"]
                 [org.clojure/core.async "0.7.559"]]
  :main ^:skip-aot asyncbug.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all}})

java -version
openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1)
OpenJDK 64-Bit Server VM (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1, mixed mode, sharing)

最终得到“Hello, World!”。

这件事情( supposed to be going on here )我真的不是很清楚,所以可能我做错了,哈哈哈哈 ...

我还用您提到的 core-async 0.6.532 版本尝试了一下,但在 32 次成功迭代后停止了 ... 然后,没有引发 AssertionError。

很抱歉我无法为您提供更多帮助。

最好的祝愿,
Florian Tauber

...