2011-11-11 189 views
4

我對Clojure很陌生,我一直在努力實現一些併發代碼。我在網上找到了這段代碼。有一個警告,它不是在Clojure中進行併發的正確方法,但我仍然想理解此代碼。瞭解這個Clojure代碼

(def *readers* (map #(agent %) '("one" "two" "three"))) 
(def *writers* (map #(agent %) '("four" "five"))) 
(def *mutex* (agent :unlocked)) 
(def *value* 0) 

; mutex implementation 
(defn lock [state who success-fn fail-fn] 
    (send who (if (= state :locked) fail-fn success-fn)) 
    :locked) 

(defn unlock [mutex] 
    :unlocked) 

; Must be invoked with send-off since this handler blocks 
(defn rand-sleep [state next-fn] 
    (Thread/sleep (rand-int 5)) 
    (send *agent* next-fn) 
    state) 

; Reader functions 
(declare try-read) 

(defn reader-got-lock [name] 
    (println (format "Thread %s says that the value is %d." name *value*)) 
    (send *mutex* unlock) 
    (send-off *agent* rand-sleep try-read) 
    name) 

(defn reader-did-not-get-lock [name] 
    (println (format "Thread %s tried to read the value, but could not." name)) 
    (send-off *agent* rand-sleep try-read) 
    name) 

(defn try-read [name] 
    (send *mutex* lock *agent* reader-got-lock reader-did-not-get-lock) 
    name) 

; Writer functions 
(declare try-write) 

(defn writer-got-lock [name] 
    (println (format "Thread %s is taking the lock." name)) 
    (def *value* (rand-int 10)) 
    (println (format "Thread %s is changing the value to %d." name *value*)) 
    (send *mutex* unlock) 
    (println (format "Thread %s is relasing the lock." name)) 
    (send-off *agent* rand-sleep try-write) 
    name) 

(defn writer-did-not-get-lock [name] 
    (println (format "Thread %s tried to write the value, but could not." name)) 
    (send-off *agent* rand-sleep try-write) 
    name) 

(defn try-write [name] 
    (send *mutex* lock *agent* writer-got-lock writer-did-not-get-lock) 
    name) 

(dorun (map #(send % try-write) *writers*)) 
(dorun (map #(send % try-read) *readers*)) 

具體我被困在這條線:

(defn try-write [name] 
    (send *mutex* lock *agent* writer-got-lock writer-did-not-get-lock) 
    name) 

應該鎖定互斥鎖,並呼籲無論是作家了鎖或作家那樣 - 不得到鎖取決於互斥州。但是*agent*在哪裏聲明,還是訪問當前代理的捷徑?那麼如何將state傳遞給鎖,在上述情況下是*agent*還是*agent*who

回答

5

*agent*是當前代理的捷徑,由clojure隱式提供。 *agent*通過爲who。最後的電話大致看起來是這樣的:

(lock @*mutex* *agent* writer-got-lock writer-did-not-get-lock) 
+0

什麼樣的結構作爲名稱在嘗試寫或結束時鎖定意味着什麼?在執行該函數之後它是否將調用者代理設置爲此狀態? – bvk256