2012-03-12 2 views
7

안녕 얘들 아 -레이스 조건 Clojure의 원자

"Changes to atoms are always free of race conditions." 

경쟁 조건의 맥락에서가 아니라 단지 변화의 관점에서 정의되지 않았습니다되지만 However- Clojure의 "원자"에 대한 내용은 해당 상태 병렬 논리 연산.

"원자에 대한 변경 사항은 항상 경쟁 조건이 없습니다"라는 보장의 의미는 무엇입니까? 자바에서는 원자 적 프리미티브가 있습니다.이 기본 프리미티브는 특정 스레드 안전 작업을 지원합니다 (예 : AtomicInteger가 "getAndIncrement"작업을 지원함). 그러나 Clojure의 원자, 예를 들면, 우리가 호출 할 수있는 입력에 독립적이다 :

(atom "Hi im a string") Or 
    (atom (.getClass Object)) 

원자 방법의 유연성은 유형 특정 원자/스레드 세이프 제공 Clojure에가 후드 아닌 "현명"임을 의미 원자에 대한 조작. 정확히 우리의 객체에 "일을"원자 방법이 무엇인지

답변

11

atom가 보장 효과적으로 원자 저장 위치 -

따라서, 물어 것 (즉, 단순히 전체 개체를 동기화하는?) 쓰레드 안전하다.

원자는 Java의 원자 데이터 유형 (예 : AtomicReference)과 유사하지만 원자가 임의의 함수를 사용하여 원자를 업데이트 할 수 있으므로 실제로는 다소 강력합니다. 실시 예 : 위의 예에서

(def a (atom "foo")) 

(defn appender [x] 
    "Higher order function that returns a function which appends a specific string" 
    (fn [s] 
    (str s x))) 

(swap! a (appender "bar")) 
=> "foobar" 

swap! 동작은 우리가 그것을 통과하는 펜더 동작은 잠재적으로 매우 복잡한 함수가 될 수있다하더라도, 원자 적으로 행동한다. 결과적으로, 원자는 원자 적 방식으로 임의의 업데이트 작업을 사용할 수 있도록합니다 (일반적으로 순수한 함수에 집중해야합니다. 충돌이 발생할 경우 함수가 여러 번 호출 될 수 있기 때문입니다).

원자는 분명히 그 안에 들어있는 객체의 스레드 안전성을 보장하지 않습니다 (예 : 비동기 Java ArrayList를 내부에 넣으면 동시 사용에는 여전히 안전하지 않음). 그러나 Clojure의 모든 불변의 데이터 유형을 사용하면 완전히 스레드로부터 안전합니다. 그러면 좋은 결과를 얻을 수 있습니다.

+5

* "이 함수들은 순차적으로 실행됩니다"* - 이것은'atom'이 보장하는 것과 정확히 일치하지 않습니다. 실제 보장은'swap af'가'a'의 값을 기억하고'f'에 전달하고'f' 후의'a'의 값이 여전히 이전 값과 같으면 그 값은 f의 결과. 그들의 효과가 서로 취소하는 한, 많은 다른 함수들이'a'에 적용될 수 있습니다. –

+1

@Rafal - 감사합니다. 조금 더 정확하게 대답을 업데이트했습니다. – mikera

+0

@myself : 기본 비교는 실제로 Java의 == (객체 ID)이므로 "동일"대신 "동일한 객체"를 참조하는 원자를 남겨두고 "서로 취소"대신 ​​"동일"이라고 써야합니다. . –