【发布时间】:2010-11-04 22:13:50
【问题描述】:
我正在尝试从网站上提供的 API 和文档中学习 Clojure。我对 Clojure 中的可变存储有点不清楚,我想确保我的理解是正确的。如果我有任何错误的想法,请告诉我。
编辑:我正在更新它,因为我收到了关于其正确性的 cmets。
免责声明:所有这些信息都是非正式的,并且可能是错误的。不要使用这篇文章来了解 Clojure 的工作原理。
Vars 总是包含一个根绑定,也可能包含一个线程绑定。它们与命令式语言中的常规变量相当,不适合在线程之间共享信息。 (感谢 Arthur Ulfeldt)
Refs 是在支持原子事务的线程之间共享的位置,这些原子事务可以更改单个事务中任意数量的 refs 的状态。在退出同步表达式(dosync)时提交事务,并使用 STM 魔法(回滚、队列、等待等)自动解决冲突
代理是通过调度独立的动作函数来改变代理的状态,使信息能够以最小的开销在线程之间异步共享的位置。代理会立即返回,因此是非阻塞的,尽管在分派的函数完成之前不会设置代理的值。
原子是可以在线程之间同步共享的位置。它们支持不同线程之间的安全操作。
以下是我基于何时使用这些结构的友好总结:
- Var 类似于命令式语言中的常规旧变量。 (尽可能避免)
- Atom 与 Vars 类似,但具有线程共享安全性,允许立即读取和安全设置。 (感谢马丁)
- Agent 类似于 Atom,但它不会阻塞它,而是生成一个新线程来计算其值,只有在更改值的过程中才会阻塞,并且可以让其他线程知道它已完成分配。
- Refs 是在事务中锁定自身的共享位置。我们无需让程序员为每段锁定代码决定竞争条件下会发生什么,而是启动一个事务并让 Clojure 处理该事务中 ref 之间的所有锁定条件。
另外,一个相关的概念是函数future。对我来说,future 对象似乎可以被描述为一个同步代理,其中在计算完成之前根本无法访问该值。它也可以被描述为一个非阻塞的 Atom。这些是对未来的准确概念吗?
【问题讨论】:
标签: multithreading clojure future mutable