📝Clojure State and Concurrency

📝Clojure State and Concurrency

Clojureの並行プログラミングについて.

up: 📂Clojure Core ref: 🏷Concurrent Programming

Clojure: 状態(State) #

状態とは,ある時系列におけるある時点での 同一実体 である.

Clojureにおいて値は immutable であり persistent である.

しかし,変更不可なオブジェクトに対して変更可能な参照を作成することで変更不可のものを管理することができる.

Clojureでは,値と同一実体を明確に区別して扱う. 4つの参照型を用意している.

  • ref: 協調的,同期的な変更を管理.
  • atom: 独立的, 同期的な変更を管理.
  • agent: 非同期な変更を管理.
  • var: スレッドローカルな変更を管理.

Clojure: atom WIKI #

Clojureにおける atom は非協調的(Independent)で同期的(Syncronous)な変更を管理する.

atomの更新ではトランザクションは不要. reset! 関数を用いる.

swap! 関数は,atomを引数にとり更新した値を返す関数を適用するための関数.

;; atomの宣言
(def foo (atom 0))

;; atomがbindされた.
foo

;; 参照先の値をリーダマクロ@で読む
@foo

;; 値の更新
(reset! foo 2)

;; 関数値の設定
(swap! foo (fn [_] (+ 1 1)))

atomでのreset! とswap!の違い #

使い分けは単なる変数をセットするだけか, 今の情報を操作をしてupdateするか.

  • reset!は今の値に関わらず値をセットする.
  • swap!は今に関数を適用する.

とはいえ, reset!とswap!は互換性がある.

Clojure Style Guide には, Prefer swap! over reset! というルールもある. とりあえず迷ったらswap!でよい.

Clojure: ref #

Clojureにおける ref は協調的(Corrdinate)で同期的(Syncronous)な変更を管理する. つまり,複数の参照を同時に更新する.

Software transactinal memory(STM) をClojureで実現するためのシンタックス.

refで宣言した値を読むには deref をつかう. リーダマクロである @ をつかって略記する.

参照先のオブジェクトを変更するには, ref-set or alter をつかう.

commute をつかうと,alterに順序保証ができる.

Clojure: agent #

Clojureにおける agent は非協調的(Independent)で非同期的(Asyncronous)な変更を管理する.

リーダーマクロ @ を利用して値を読む.

send メソッドを利用することで,値を更新する. 正確には, send メソッドの引数でagentを更新するための関数値を与えると,Clojureはその処理をスレッドプールでの処理エンキューしてあとはClojureがよろしく実行してくれる.

send-off を利用すると, スレッドプールが必要に応じて動的に拡張されるので,わかりやすく言えばすぐに実行される.ファイル書き込みなどのようなBlocking I/O, 1つの処理によってスレッドが止まってしまう場合に自動で別のスレッドが作られて実行される.

スレッドプールのスレッドをつかってClojureが暇なときに実行するため, いつagentの値が更新されたかわからない. 待ち合わせには await を利用する.

agentの値の更新化失敗すると,それ以後のagentの更新はできなくなる. フタをしてしまうようなもの. agent-errors に失内容が入っている. また, set-error-mode! メソッドで :continue を指定すると続行することもできる.

Clojure: deref #

as known as @ reader macro

状態の読み出しに利用できるリーダマクロだが, 何でも読める.atomだろうとrefだろうとagentだろう, futureもpromiseも.

Clojure Threading Macros だと deref を使うのかな? best practiceがわからない.

Active Recalls #

Clojureにおいて状態を示す変数を宣言するための4つのシンタックスは? #

atom, ref, agent, var

Clojureのatomとrefの違いはなんですか? #

複数のrefの更新にはトランザクションを使って協調させる必要があるが,atomは単一の値を独立に更新することができる.

Clojureのatomとrefを更新するための関数はそれぞれなんですか?また参照ためのリーダーマクロは? #

atomはreset!, refは alter. @で値が読める.

Clojureのdefとatomの違いはなんですか? #

defは値を定義するためのシンタックスであり,値は不変であり永続的である.

atomは同一実体であり,参照先の値が入れ替わっても参照元のシンボルは不変である.

ClojureにおけるSTMを実現するシンタックスはなんですか?またトランザクションを示すシンタックスは? #

refでSTMを宣言し,dosyncマクロでトランザクションを張る.

Clojureのagentの2つの特徴はなんですか? #

非協調的(Independent)であり非同期(Asyncronous).

Clojureのsendとsend-offの違いはなんですか? #

どちらもagentの値を更新するためのものだが,send-offはファイル書き込みなどの1つの処理によってスレッドが止まってしまう場合に自動で別のスレッドが作られて実行される.


Tags