In Clojure, almost everything is a value.
State is the value of an identity at a point in time.
For identity, four types of references are available in Clojure.
- Refs, making changes to the shared state in a coordinated,synchronous manner
- Atoms, changing the shared state in uncoordinated,synchronous mode
- Agents, changing the shared state in asynchronous mode
- Vars, manages thread local state.
Ref and soft transaction memory (software transactional memories)
;Clojure中大部分对象都是不可变的。如果需要可变数据,如下定义一个引用。(def current-track (ref "Mars, the Bringer of War"))->#‘user/current-track;解引用(deref current-track)->"Mars, the Bringer of War"@current-track->"Mars, the Bringer of War"
Ref-set
;给引用设置新的值(ref-set);由于引用可变,因而需要在dosync开启的事务内进行。(dosync (ref-set current-track "Venus, the Bringer of Peace"))
Properties of STM
;正如数据库事务一样,STM事务有三个性质。;原子性(atomic);一致性(consistent),引用类型可以指明校验函数,任何一个校验失败,事务失败。;隔离性(isolated),事务之间不可见。;然而数据库事务还有一个特性,可持久性(durable)。由于STM是内存中事务,无法保证持久性。事务的四个性质简称为ACID,STM只提供了ACI。;在同一个事务中发生的变更,称之为coordinated,即在外界看来这些变更同时发生。(dosync (ref-set current-track"Credo") (ref-set current-composer"Byrd"))-> "Byrd"
Alter
;更新引用,使用alter可以接受一个变更函数,函数的参数包含引用当前值,返回值即为引用的新值。(defrecord Message [sender text])(def messages (ref ()))(defn add-message [msg](dosync (alter messages conj msg)))
How STM works: MVCC
The technology used by STM is called Multiversion Concurrency Control
Simply put, transaction a begins by acquiring an integer (point) that represents the timestamp, and a private copy of all referenced values involved (effectively private copy). All operations are carried out against this private copy, and a will force a restart if any other transaction attempts to set/alter the references involved in the process. If an exception is thrown in the DoSync, the transaction ends and no more retries are made.
Sometimes you feel that alter
this excess of caution is unnecessary and can be used with better performancecommute
Commute
Commute is a special variant of Alter, which allows for more concurrency. Of course, as the name of the function indicates, the order of the changes initiated by commute is variable, i.e. the STM can have the freedom of reordering. The current transaction does not restart because another transaction changed the reference. In theory, the update of chat records should not use commute, however, the de-commute of the actual STM occurs at a subtle level, so there is no impact.
Prefer to use alter
The order of many data updates is non-exchangeable (not commutative). For example, a counter that produces a unique ID.
(def counter (ref 0))(defn next-counter [] (dosync (alter counter inc)))
In other cases try to use alter instead of commute, because alter is not prone to error, the biggest problem is that efficiency may be lower.
To add a checksum to ref
Database transactions perform many integrity checks in order to ensure consistency. STM can also perform a similar check by adding a check function to ref.
(def validate-message-listevery#(and (:sender %) (:text %))))(def messages (ref () :validator validate-message-list"not a valid message"reference state
Using Atom for non-coordinated synchronization updates
Atoms is a lighter-weight mechanism than a coordinated (coordinated) ref update of a transaction. Used for non-coordinated updates to a single value.
; Define an Atom (Def current-track (Atom "Venus, the Bringer of Peace")) # ' User/current-track; Dereference Atom (deref current-track) "Venus, the Bringer of Peace"@current-track - "Venus, the Bringer of Peace"; Set a new value (reset! current-track "Credo") "Credo"; use atom to point to a map (Def current-track (Atom {: Title "Credo" : Composer "Byrd"}) # ' User/current-track; re-set map (reset! current-track {: Title "Spem in Alium" : Composer "Tallis"}){: Title"Spem in Alium",: Composer"Tallis"Just set a field of map and use the swap! function (swap! current-track assoc:title "Sancte Deus"){: Title"Sancte Deus",: Composer"Tallis"}
Using the agent for asynchronous updates
;定义一个Agent(def counter (agent 0))->#‘user/counter;通知Agent更新数据,注意是异步的(send counter inc)->#<[email protected]: 0>
Programming Clojure notes of five--state