更改 Clojure 引用的线程越多,每个线程的重试率就越高吗?
我有点担心这个。
想象一下最简单的版本控制方式,程序员只需从主存储库复制所有目录,并在更改文件后,如果主存储库仍然相同,则执行相反的操作。如果已被其他人更改,他们必须重试。
当程序员数量增加时,重试次数自然也会增加,但可能与程序员数量不成正比。
如果十个程序员工作,每人一项工作需要一个小时,那么完成所有工作至少需要十个小时。
如果他们认真的话,大约 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)))
CPU:2.93GHz 四核 Intel Core 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
我将作业更改为 (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
在线程/睡眠情况下,我认为重试次数可能会增加超过此结果,因为 CPU 可用。
为什么重试次数没有增加?
谢谢。
I worry about this a little.
Imagine the simplest version controll way that programmers just copy all directory from the master repository and after changing a file do reversely if the master repository is still the same. If it has been changed by another, they must try again.
When the number of programmers increases, it is natural that retries also increase, but it might not be proportional to the number of programmers.
If ten programmers work and a work takes an hour per person, to complete all work ten hours are needed at least.
If they are earnest, about 9 + 8 + 7 + ... 1 = 45 man-hours come to nothing.
In a hundread of programmers, about 99 + 98 + ... 1 = 4950 man-hours come to nothing.
I tried to count the number of retries and got the results.
Source
(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)))
CPU: 2.93GHz Quad-Core Intel Core i7
result
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
I changed the job to (Thread/sleep n) instead of (fib n) and got similar results.
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
In Thread/sleep case, I think retries could increase more than this result because CPU is available.
Why don't retries increase?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
因为您实际上并没有生成 10、100 或 1000 个线程!创造
未来
并不总是创建新线程。它使用 背后的线程池它不断对作业进行排队的场景(或者技术上的“Runnable”)。线程池是一个缓存的线程池,它重用线程来运行作业。所以在你的例子中,你实际上并没有产生 1000 个线程。如果您想查看实际的重试,请获取低于
future
的级别 - 创建您自己的线程池并将Runnable
推入其中。Because you are not actually spawning 10, 100 or 1000 threads! Creating a
future
does not always create a new thread. It uses a thread pool behind the scenes where it keeps queuing the jobs (orRunnable
s to be technical). The thread pool is a cached thread pool which reuses the threads for running the jobs.So in your case, you are not actually spawning a 1000 threads. If you want to see the retries in action, get a level below
future
- create your own thread pool and pushRunnable
s into it.自我回答
我已经修改了 main 函数,不使用 pmap 并得到了结果,其结果是按计算得出的。
fib
线程/睡眠
self answer
I have modified main function not to use pmap and got results, which work out as calculated.
fib
Thread/sleep