2017-03-02 12 views
0

나는 clojure을 처음 사용하고 있으며, 예 : bank account transfer이라는 고전적인 동시성 사례를 구현하려고합니다. transactional memory을 사용하여 구현하고 싶습니다. 여기 clojure 은행 계좌 송금 사례

내 구현에 java

static class Account { 
    private double balance; 

    public synchronized void withdraw(double value) { 
     balance -= value; 
    } 

    public synchronized void deposit(double value) { 
     balance += value; 
    } 
} 

static synchronized void transfer(Account from, Account to, double amount) { 
    from.withdraw(amount); 
    to.deposit(amount); 
} 

확실하지의 예이지만 유효한 것 같다.

그리고 여기가 clojure

(deftype Account [balance]) 

(def account1 (Account. (ref 100))) 
(def account2 (Account. (ref 100))) 

(defn print-accs [] 
    (println " account 1 => " (deref (.balance account1)) 
      " account 2 => " (deref (.balance account2)))) 

(defn transfer [from to amount] 
    (dosync 
     (alter (.balance from) - amount) 
     (alter (.balance to) + amount))) 

(print-accs) ; 100 100 

(transfer account1 account2 10) 

(print-accs) ; 90 110 

내 코드는 transactional memory 또는 모든 bank account transfer의 올바른 구현을 사용의 적절한 예이다? 나는 ref는 필드에 올바른 사용 했 또는 전체 Account 예를 들어 그것을 사용해야?

+0

오타? 당신은'에서'로 넘어가지만 나중에'account [12]' – cfrick

+0

오 실제로 사용하십시오. Fixed – lapots

답변

3

deftype은 필요하지 않지만 그렇지 않으면 좋아 보인다. 내가 권하고 싶습니다

(def account1 (ref 100)) 
(def account2 (ref 100)) 

(defn print-accs [] 
    (println " account 1 => " @account1 
      " account 2 => " @account2)) 

(defn transfer [from to amount] 
    (dosync 
     (alter account1 - amount) 
     (alter account2 + amount))) 

(print-accs) ; 100 100 

(transfer account1 account2 10) 

(print-accs) ; 90 110 

한 가지 review The Clojure Cheatsheet에이고 항상 열려 브라우저 탭을 계속 : 좀과 같이 간단합니다. 링크는 ClojureDocs.org, such as that for dosync에 대한 자세한 정보로 연결됩니다. 즐겨!

계정 잔고와 같은 단일 값에 대한

업데이트, Account 레코드의 균형을 포장에 많은 지점이 없다. 당신이 모두 같은 필드가 레코드 그룹을 만들려면, 당신은 아마 defrecord를 원하는 : 그것은 & 유연하고 간단하기 때문에

(defrecord Account [name balance]) 

대부분의 애플리케이션은

(def joe-acct (ref {:name "Joe" :balance 100.00}) 

같은 일반지도를 사용하여 시작. 당신은 항상 이름 & 균형으로 구성되어지도에 유형 이름을 부여 할 경우 나중에, 당신은

(defrecord Account [name balance]) 
(def joe-acct (ref (Account. "Joe" 100.00))) 

deftype는 "낮은 수준"으로 간주하고 거의 현재 사용되지로 전환 할 수 있습니다. 참조 :`transfer`에서

+0

글쎄, 나는'Account'를위한 특정 클래스를 만드는 것을 모방하길 원했기 때문에'deftype'을 사용했습니다. 그래서 나는 확실하지 않기 때문에'balance' 필드의'Account' 인스턴스에'Ref'를 저장해야하는지에 대해 질문했습니다. – lapots

+0

BTW, 'Refs'가 메모리에서 제거 될 때 우연히 알고 있습니까? GC로? 참조 될 때 더 이상 – lapots

+1

의 Ref 다른 같은 "개체"입니다, 그것은 GC에 의해 제거된다. –