Java 플랫폼은 조건 변수를 지원합니다. java.util.concurrent.locks.Condition
에 대한 설명서를 참조하십시오.
상기 페이지에서 예 Clojure의로 쉽게 변환 :
;;; based on the example in java.util.concurrent.locks.Condition
;;; documentation for JDK 1.7, see the link above
(defprotocol PBoundedBuffer
(-put [buf x])
(-take [buf]))
(import (java.util.concurrent.locks ReentrantLock Condition))
(deftype BoundedBuffer [^ReentrantLock lock
^Condition not-full?
^Condition not-empty?
^objects items
^:unsynchronized-mutable ^int putptr
^:unsynchronized-mutable ^int takeptr
^:unsynchronized-mutable ^int cnt]
PBoundedBuffer
(-put [buf x]
(.lock lock)
(try
(while (== cnt (alength items))
(.await not-full?))
(aset items putptr x)
(set! putptr (unchecked-inc-int putptr))
(if (== putptr (alength items))
(set! putptr (int 0)))
(set! cnt (unchecked-inc-int cnt))
(.signal not-empty?)
(finally
(.unlock lock))))
(-take [buf]
(.lock lock)
(try
(while (zero? cnt)
(.await not-empty?))
(let [x (aget items takeptr)]
(set! takeptr (unchecked-inc-int takeptr))
(if (== takeptr (alength items))
(set! takeptr (int 0)))
(set! cnt (unchecked-dec-int cnt))
(.signal not-full?)
x)
(finally
(.unlock lock)))))
(defn bounded-buffer [capacity]
(let [lock (java.util.concurrent.locks.ReentrantLock.)]
(BoundedBuffer. lock
(.newCondition lock)
(.newCondition lock)
(object-array capacity)
0
0
0)))
REPL에서 시운전 : 원하는
(def bb (bounded-buffer 3))
(-put bb 1)
(-put bb 2)
(-put bb 3)
(future (-put bb 4) (println :foo))
(-take bb)
가 미래 블록 후 최종 호출 후 :foo
를 인쇄 -take
.
무슨 일이 있었을 #clojure 로그를 살펴보면 실제로 공유 리소스가 공유 리소스를 사용하는 스레드에 의해 독점적으로 보관 된 다음 다음 스레드가 한 번 픽업 할 수 있도록 "사용 가능"상태로 돌아가는 시나리오에 관심이있는 것으로 보입니다 현재 스레드가 더 이상 필요하지 않습니다. 크기가 1 인 버퍼를 가진 채널을 사용하여 core.async로 할 수 있습니다 : (1) 채널을 생성합니다 -'(chan 1)', 적절한 곳에 넣고 채널에 자원을 넣으십시오; (2)'( !! '와 함께 반환하십시오. –