Skip to main content
 首页 » 编程设计

multithreading之Clojure 可变存储类型

2024年10月25日12xiaohuochai

我正在尝试从网站上提供的 API 和文档中学习 Clojure。我对 Clojure 中的可变存储有点不清楚,我想确保我的理解是正确的。如果有任何想法我错了,请告诉我。

编辑:当我收到关于其正确性的评论时,我正在更新它。

免责声明:所有这些信息都是非正式的并且可能是错误的。不要使用这篇文章来了解 Clojure 的工作原理。

变量 总是包含一个根绑定(bind),可能还有一个每个线程的绑定(bind)。它们与命令式语言中的常规变量相当,不适合在线程之间共享信息。 (感谢亚瑟乌尔费尔特)

引用 是支持原子事务的线程之间共享的位置,这些原子事务可以更改单个事务中任意数量的引用的状态。在退出同步表达式(dosync)时提交事务,并使用 STM 魔法(回滚、队列、等待等)自动解决冲突

代理商是通过调度独立的 Action 函数来改变代理的状态,使信息能够以最小的开销在线程之间异步共享的位置。代理会立即返回,因此是非阻塞的,尽管在分派(dispatch)函数完成之前不会设置代理的值。

原子是可以在线程之间同步共享的位置。它们支持不同线程之间的安全操作。

这是我基于何时使用这些结构的友好总结:

  • Vars 就像命令式语言中的常规旧变量。 (尽可能避免)
  • Atom 类似于 Vars,但具有线程共享安全性,允许立即读取和安全设置。 (感谢马丁)
  • 代理就像一个原子,但它不会阻塞它会产生一个新线程来计算它的值,只有在更改值的过程中才会阻塞,并且可以让其他线程知道它已完成分配。
  • Refs 是在事务中锁定自己的共享位置。我们不需要让程序员决定在每段锁定代码的竞争条件下会发生什么,我们只需启动一个事务并让 Clojure 处理该事务中 ref 之间的所有锁定条件。

  • 另外,一个相关的概念是函数 future。 .对我来说,future 对象似乎可以被描述为一个同步代理,其中在计算完成之前根本无法访问该值。它也可以被描述为一个非阻塞的 Atom。这些是对 future 的准确概念吗?

    请您参考如下方法:

    听起来你真的在使用 Clojure!做得好 :)

    Vars 在所有线程中都有一个可见的“根绑定(bind)”,每个单独的线程都可以更改它看到的值,而不会影响其他线程。如果我的理解是正确的,那么一个 var 不能只存在于一个线程中而没有一个对所有人可见的根绑定(bind),并且在第一次使用 (def ... ) 定义它之前它不能“反弹”。

    Refs 在包含更改的 (dosync ... ) 事务结束时提交,但仅在事务能够以一致状态完成时提交。