【问题标题】:synchronized counter in clojureClojure中的同步计数器
【发布时间】:2011-09-18 12:47:44
【问题描述】:

如果我想保留一个全局计数器(例如,计算跨多个线程的传入请求数),那么在 java 中最好的方法是使用 volatile int。假设正在使用 clojure,有没有更好(更好的吞吐量)的方法?

【问题讨论】:

    标签: multithreading clojure volatile


    【解决方案1】:

    我会在 Clojure 中使用 atom 来做到这一点:

    (def counter (atom 0N))
    
    ;; increment the counter
    (swap! counter inc)
    
    ;; read the counter
    @counter
    => 1
    

    这是完全线程安全的,而且性能惊人。此外,由于它使用 Clojure 的任意精度数字处理,它不会像 volatile int 那样容易受到整数溢出的影响.....

    【讨论】:

    • 它会比使用 volatile int 提供更好的吞吐量吗?如果是,任何关于为什么/如何更好的见解。
    • 原子会比 volatile int 慢一点。但除非您每秒计算数百万个事件,否则差异不会大到足以引起注意。在那个吞吐量水平下,一个 volatile int 无论如何都会在不到一个小时内溢出......
    • 在 Clojure 1.3 上,它可以溢出:(swap! (atom 9223372036854775807) inc) 抛出溢出异常。解决方法是使用 BigInts:(swap! (atom 9223372036854775807N) inc) 或自动提升 inc' 函数
    • 好点贾斯汀(我还在 1.2 上)。猜猜修复是用 BigInt 初始化计数器.....现在修改它
    【解决方案2】:

    将全局计数器定义为agent

    (def counter (agent 0))
    

    要增加代理中包含的值,您将send 一个函数(在本例中为inc)添加到代理:

    (send counter inc)
    

    要读取当前值,您可以使用deref@ 读取器宏:

    @counter ;; same as (deref counter)
    

    代理只是几种可用的引用类型之一。您可以在 Clojure 网站上阅读有关这些内容的更多信息:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 2012-01-15
      • 1970-01-01
      • 2021-06-27
      • 2012-09-25
      • 1970-01-01
      • 2011-11-15
      相关资源
      最近更新 更多