Vars

Vars 是一种可以有一个被所有线程共享的root binding并且每个线程线程还能有自己线程本地(thread-local)的值的一种引用类型。

下面的语法创建一个Var并且给它一个root binding:

(def <em>name</em> <em>value</em>)

你可以不给它一个值的。如果你没有给它一个值,那么我们说这个Var是 "unbound". 同样的语法可以用来修改一个Var的root binding。

有两种方法可以创建一个已经存在的Var的线程本地binding(thread-local-binding):

(binding [<em>name</em> <em>expression</em>] <em>body</em>)
(set! <em>name</em> <em>expression</em>) ; inside a binding that bound the same name

关于binding宏的用法我们前面已经介绍过了. 下面的例子演示把它和 set! 一起使用. 用set!来修改一个由binding bind的Var的线程本地的值。

(def v 1)

(defn change-it []
  (println "2) v =" v) ; -> 1

  (def v 2) ; changes root value
  (println "3) v =" v) ; -> 2

  (binding [v 3] ; binds a thread-local value
    (println "4) v =" v) ; -> 3

    (set! v 4) ; changes thread-local value
    (println "5) v =" v)) ; -> 4

  (println "6) v =" v)) ; thread-local value is gone now -> 2

(println "1) v =" v) ; -> 1

(let [thread (Thread. #(change-it))]
  (.start thread)
  (.join thread)) ; wait for thread to finish

(println "7) v =" v) ; -> 2

我们一般不鼓励使用 Vars, 因为线程之间对于同一个Var的修改没有做很好的协调,比如线程A在使用一个Var的root值,然后才发现,在它使用这个值的时候,已经有一个线程B在修改这个值了。