对比clojure.lang.Ref
和clojure.lang.Atom
的源代码,我发现它们都是从clojure.lang.ARef
继承而来的。
在clojure.lang.ARef
中有一个函数notifyWatches
,它让所有监视功能知道已进行更改。
clojure.lang.Atom
调用中的swap!
和reset!
函数在其实现中notifyWatches
。
例如。
public Object swap(IFn f) {
for(; ;)
{
Object v = deref();
Object newv = f.invoke(v);
validate(newv);
if(state.compareAndSet(v, newv))
{
notifyWatches(v, newv);
return newv;
}
}
}
但是,当我在clojure.lang.Ref
中搜索notifyWatches
时,它什么也没找到。alter
函数如下所示。
public Object alter(IFn fn, ISeq args) {
LockingTransaction t = LockingTransaction.getEx();
return t.doSet(this, fn.applyTo(RT.cons(t.doGet(this), args)));
}
如果没有方法调用 notifyWatches,引用的所有监视函数如何收到通知?
要查找notifyWatches
的调用发生在LockingTransaction
类的run
方法中。
对引用的更改发生在事务中。 请注意,对 LockingTransaction
的 doSet
方法的调用传递this
(对 Ref 的引用)。将在事务中应用的更改由doSet
方法建立,但该更改在LockingTransaction
run
方法中生效。当事务成功运行时notifyWatches
将使用对 doSet
记录的 Ref 的引用进行调用。
clojure.lang.Ref 扩展了 clojure.lang.ARef,其中包含监视并提供 notifyWatches 方法