更改Clojure ref的线程越多,每个线程的重试率就越高?

Tak*_*umi 4 multithreading clojure refs

我有点担心.
想象一下,最简单的版本控制方式是程序员只是从主存储库复制所有目录,如果主存储库仍然相同,则在更改文件后会反向执行.如果它被另一个人改变了,他们必须再试一次.

当程序员的数量增加时,重试也会增加,但它可能与程序员的数量不成比例.
如果十名程序员工作并且每人工作需要一个小时,那么至少需要完成所有工作十小时.
如果他们认真,大概9 + 8 + 7 + ...... 1 = 45工时无济于事.
在程序员看来,大约99 + 98 + ... 1 = 4950工时无济于事.

我试着计算重试次数并得到结果.

资源

(defn fib [n] 
   (if  (or (zero? n) (= n 1)) 
       1 
      (+  (fib (dec n) )  (fib (- n 2))))) 

(defn calc! [r counter-A counter-B counter-C n]
  (dosync
   (swap! counter-A inc)
   ;;(Thread/sleep n)
   (fib n)
   (swap! counter-B inc)
   (alter r inc)
   (swap! counter-C inc)))

(defn main [thread-num n]
  (let [r (ref 0)
        counter-A (atom 0)
        counter-B (atom 0)
        counter-C (atom 0)]
    (doall (pmap deref
              (for [_ (take thread-num (repeat nil))]
                (future (calc! r counter-A counter-B counter-C n)))))
    (println thread-num " Thread. @ref:" @r)
    (println "A:" @counter-A ", B:" @counter-B ", C:" @counter-C)))
Run Code Online (Sandbox Code Playgroud)

CPU:2.93GHz四核英特尔酷睿i7测试
结果

user> (time (main 10 25))
10  Thread. @ref: 10
A: 53 , B: 53 , C: 10
"Elapsed time: 94.412 msecs"
nil
user> (time (main 100 25))
100  Thread. @ref: 100
A: 545 , B: 545 , C: 100
"Elapsed time: 966.141 msecs"
nil
user> (time (main 1000 25))
1000  Thread. @ref: 1000
A: 5507 , B: 5507 , C: 1000
"Elapsed time: 9555.165 msecs"
nil
Run Code Online (Sandbox Code Playgroud)

我将工作改为(Thread/sleep n)而不是(fib n),并得到了类似的结果.

user> (time (main 10 20))
10  Thread. @ref: 10
A: 55 , B: 55 , C: 10
"Elapsed time: 220.616 msecs"
nil
user> (time (main 100 20))
100  Thread. @ref: 100
A: 689 , B: 689 , C: 117
"Elapsed time: 2013.729 msecs"
nil
user> (time (main 1000 20))
1000  Thread. @ref: 1000
A: 6911 , B: 6911 , C: 1127
"Elapsed time: 20243.214 msecs"
nil
Run Code Online (Sandbox Code Playgroud)

在线程/睡眠情况下,我认为重试可能会增加超过此结果,因为CPU可用.
为什么不重试增加?

谢谢.

Abh*_*kar 5

因为你实际上并没有产生10,100或1000个线程!创建future 并不总是创建新线程.它在后台使用一个线程池,它那里排队工作(或者Runnables是技术性的).线程池是一个缓存的线程池,它重用线程来运行作业.

所以在你的情况下,你实际上并没有产生1000个线程.如果你想看到重试的情况,请获得以下级别future- 创建自己的线程池并将其推Runnable入其中.