通勤如何工作?

CHA*_*APa 1 concurrency clojure

真正的通勤方式.(通勤身份功能和价值观)

Clojure文档说:

用法:(通勤ref fun&args)

必须在事务中调用.将ref的in-transaction-value设置为:

(应用有趣的in-transaction-value-of-ref args)并返回ref的in-transaction-value.

在事务的提交点,将ref的值设置为:

(应用最近最具承诺价值的参考args)

因此,通勤形式分两个阶段进行.

是第二阶段原子?(应用最近最具承诺价值的参考args)

如果没有,在这个例子中发生了什么:2个线程(T1和T2).

两者都会增加(交换功能)相同的身份.

 IDENTITY: (def i (ref 0 ) 
        (dosync (commute inc i ) )
Run Code Online (Sandbox Code Playgroud)

通勤呼叫inc的第一步中的T1,其中ref i = 0(在事务值= 1)

T1停止

通勤调用inc的第一步中的T2,ref i = 0(在事务值= 1)

T2停止

第二步中的T1再次调用inc,最近提交值i = 0,inc函数返回但更新前ref(i)T1停止

第二步中的T2再次使用最近的提交值i = 0调用inc并更新引用

T1再次启动并使用inc返回值= 1更新引用

这是竞争条件问题?如何避免这种情况?如果第二阶段是原子的,那就不会发生.

提前致谢

更新:如果我理解正确的通勤操作(提交点)的最后阶段是同步"LOCK通勤乐趣UNLOCK**"?

小智 5

关键是要意识到ref的in-transaction值(由通勤产生)实际上可能与最终在提交点写入ref的值不同.

在你的例子中,线程T1和T2同时运行它们的事务,我指的是0.它们都是(inc i)通过通信,因此在它们的事务中都看到i = 1.但是,当它们准备提交时,commute(inc)中指定的函数将使用最近提交的值应用于ref .因此,如果T1先提交,i = 1,则T2提交,i = 2.在回答你的问题时,这些提交确实是原子的,所以没有竞争条件是可能的.

我引用下面的通勤文件:

在事务的提交点,将ref的值设置为:

(apply fun most-recently-committed-value-of-ref args)

因此,fun应该是可交换的,或者,如果失败,则必须接受last-one-in-wins行为.

"最后一次胜利"位警告你,如果你正在应用的函数不是可交换的 - 想到矩阵乘法 - 那么事实上竞争条件可能的.即,首先提交的事务将其功能应用于"原始"ref值,并且下一个要提交的事务将其功能应用于更新状态.但是,函数应用程序仍然以原子方式应用.