Clojure可变存储类型

Kai*_*Kai 27 multithreading future clojure mutable

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

编辑:我正在更新这个,因为我收到有关其正确性的评论.


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


Vars总是包含根绑定,可能还包含每个线程的绑定.它们与命令式语言中的常规变量相当,不适合在线程之间共享信息.(感谢Arthur Ulfeldt)

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

代理是通过调度独立的操作函数来更改代理的状态,使得线程之间异步共享信息的位置,而开销最小.虽然在调度函数完成之前未设置代理程序的值,但代理程序会立即返回并因此是非阻塞的.

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

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

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

此外,相关概念是功能future.对我来说,似乎未来的对象可以被描述为同步代理,在完成计算之前根本无法访问该值.它也可以描述为非阻塞Atom.这些准确的未来概念是什么?

Art*_*ldt 5

听起来你真的得到了Clojure!做得好 :)

Vars在所有线程中都有一个"根绑定",每个单独的线程都可以更改它看到的值,而不会影响其他线程.如果我的理解是正确的,var只能在一个线程中不存在,并且所有人都可以看到root绑定,并且它不能"反弹",直到第一次使用(def ...)定义它.

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