2017-02-15 8 views
0

Clojureを初めて使用し、トランザクションモデルを理解しようとしています。 altercommuteで遊んでいるとき、私はの後にrefをcommuteとした場合、トランザクションは何もコミットしない(または何も変更しない)ことに気付きました。Clojure:1つのトランザクション内で変更する前に通勤するとトランザクションが失敗する

例えば:

(def counter (ref 0)) 
(def i (ref 0)) 
(future (dosync 
      (ref-set counter 1) 
      (ref-set i 1) 
      (commute counter inc) 
      (alter counter inc))) 

@counter@i両方が0になり、私はcommutealterを交換するか、この場合、2つのcommute S又は二alter Sを使用する場合、それは、所望の結果を生成する(図3及び1)。

私はcommutealterの行動はそのcommuteで少し異なっていることを説明するいくつかの記事を読んだが、実際のトランザクション(それはスタンド1、「コミット」の段階で他)で2回実行し、一貫性のない無視されますrefのスナップショット。私はちょうどこれらの2つの組み合わせの奇妙な動作に混乱しています。

誰でもどのように動作するのか説明できますか?前もって感謝します!

+0

clojure 1.8:これはrepl '{:status:failed、:val #error {:原因"通勤の後に設定できません ":via {{:type java.util.concurrent.ExecutionException ...' so '通勤 'の後に'変更'しないでください。特定のドキュメントを見つけることができませんでした - ちょうど[ソース](https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LockingTransaction.java#L428) – birdspider

答えて

0

commute機能は、それがは、更新機能の追加の再試行のコストでロック競合を減少させることができる非常に狭い(すなわち稀な)状況において有用です。あなたの例が示すように、トランザクションの精神モデルをはるかに複雑にしています(前にこのような問題は見たことがありません)。

alterは、より簡単で防弾性が高いので、commuteの代わりにalterを使用することがほとんど常に良いです。確かに、私は通常commuteの使用をの早期最適化のケースとみなします。

関連する問題