The account problem in Java and
            Clojure




          Alf Kristian Støyle
public class Account {

     private long balance;
      private final int accountNo;


    public void debit(long debitAm...
public class Account {

     private volatile long balance;
      private final int accountNo;


    public synchronized v...
public void transfer(Account fromAccount, Account toAccount,
                     long amount) throws Exception {

    if ...
public void transfer(Account fromAccount, Account toAccount,
                     long amount) throws Exception {

    syn...
public void transfer(Account fromAccount, Account toAccount,
                     long amount) throws Exception {

    Obj...
public class Account {
             private volatile long balance;
             private final int accountNo;

            ...
Clojure
Clojure
• Pure functional
Clojure
• Pure functional
• Managed references
 • Ref
 • ...
Clojure
• Pure functional
• Managed references
 • Ref
 • ...
• Software transactional memory
(defn transfer [from-account to-account amount]
  (dosync
    (if (> amount @from-account)
      (throw (Exception. "Not e...
(defn transfer [from-account to-account amount]
  (dosync
    (if (> amount @from-account)
      (throw (Exception. "Not e...
(defn transfer [from-account to-account amount]
  (dosync
    (if (> amount @from-account)
      (throw (Exception. "Not e...
(defn transfer [from-account to-account amount]
  (dosync
    (if (> amount @from-account)
      (throw (Exception. "Not e...
(defn transfer [from-account to-account amount]
  (dosync
    (if (> amount @from-account)
      (throw (Exception. "Not e...
(defn transfer [from-account to-account amount]
  (dosync
    (if (> amount @from-account)
      (throw (Exception. "Not e...
The pragmatic programmers




“Learn at least one new language every year”
Upcoming SlideShare
Loading in...5
×

The account problem in Java and Clojure

1,210

Published on

This presentation shows how bad Java is at handling concurrency, and how good Clojure is at handling the same problem.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,210
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
20
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide












  • * One mutable field -> real app
    * Reason about -> honestly
    * Difficult test
    * Inherently difficult with locks
  • everything is immutable. -> List
  • everything is immutable. -> List
  • everything is immutable. -> List
  • Claim a lot simpler than the Java version
    * easier to reason
    * easier to test
    -> no deadlocking
  • Claim a lot simpler than the Java version
    * easier to reason
    * easier to test
    -> no deadlocking
  • Claim a lot simpler than the Java version
    * easier to reason
    * easier to test
    -> no deadlocking
  • Claim a lot simpler than the Java version
    * easier to reason
    * easier to test
    -> no deadlocking
  • Claim a lot simpler than the Java version
    * easier to reason
    * easier to test
    -> no deadlocking
  • Claim a lot simpler than the Java version
    * easier to reason
    * easier to test
    -> no deadlocking
  • Good reason to look at Clojure.
  • The account problem in Java and Clojure

    1. 1. The account problem in Java and Clojure Alf Kristian Støyle
    2. 2. public class Account { private long balance; private final int accountNo; public void debit(long debitAmount) { this.balance -= debitAmount; } public void credit(long creditAmount) { this.balance += creditAmount; } public long getBalance() { return this.balance; } public void getAccountNo() { return this.accountNo; } }
    3. 3. public class Account { private volatile long balance; private final int accountNo; public synchronized void debit(long debitAmount) { this.balance -= debitAmount; } public synchronized void credit(long creditAmount) { this.balance += creditAmount; } public synchronized long getBalance() { return this.balance; } public void getAccountNo() { return this.accountNo; } }
    4. 4. public void transfer(Account fromAccount, Account toAccount, long amount) throws Exception { if (fromAccount.getBalance() < amount) { throw new Exception("Not enough money!"); } fromAccount.debit(amount); toAccount.credit(amount); }
    5. 5. public void transfer(Account fromAccount, Account toAccount, long amount) throws Exception { synchronized (fromAccount) { synchronized (toAccount) { if (fromAccount.getBalance() < amount) { throw new Exception("Not enough money!"); } fromAccount.debit(amount); toAccount.credit(amount); } } }
    6. 6. public void transfer(Account fromAccount, Account toAccount, long amount) throws Exception { Object mutex1 = toAccount; Object mutex2 = fromAccount; if (fromAccount.getAccountNo() > toAccount.getAccountNo()) { mutex1 = fromAccount; mutex2 = toAccount; } synchronized (mutex1) { synchronized (mutex2) { if (fromAccount.getBalance() < amount) { throw new Exception("Not enough money!"); } fromAccount.debit(amount); toAccount.credit(amount); } } }
    7. 7. public class Account { private volatile long balance; private final int accountNo; public synchronized void debit(long debitAmount) { this.balance -= debitAmount; } public synchronized void credit(long creditAmount) { this.balance += creditAmount; } public synchronized long getBalance() { return this.balance; } public void getAccountNo() { return this.accountNo; } } public void transfer(Account fromAccount, Account toAccount, long amount) throws Exception { Object mutex1 = toAccount; Object mutex2 = fromAccount; if (fromAccount.getAccountNo() > toAccount.getAccountNo()) { mutex1 = fromAccount; mutex2 = toAccount; } synchronized (mutex1) { synchronized (mutex2) { if (fromAccount.getBalance() < amount) { throw new Exception("Not enough money!"); } fromAccount.debit(amount); toAccount.credit(amount); } } }
    8. 8. Clojure
    9. 9. Clojure • Pure functional
    10. 10. Clojure • Pure functional • Managed references • Ref • ...
    11. 11. Clojure • Pure functional • Managed references • Ref • ... • Software transactional memory
    12. 12. (defn transfer [from-account to-account amount] (dosync (if (> amount @from-account) (throw (Exception. "Not enough money!"))) (alter from-account - amount) (alter to-account + amount)))
    13. 13. (defn transfer [from-account to-account amount] (dosync (if (> amount @from-account) (throw (Exception. "Not enough money!"))) (alter from-account - amount) (alter to-account + amount))) OMG it’s a Lisp!
    14. 14. (defn transfer [from-account to-account amount] (dosync (if (> amount @from-account) (throw (Exception. "Not enough money!"))) (alter from-account - amount) (alter to-account + amount)))
    15. 15. (defn transfer [from-account to-account amount] (dosync (if (> amount @from-account) (throw (Exception. "Not enough money!"))) (alter from-account - amount) (alter to-account + amount))) (def account-a (ref 1000)) (def account-b (ref 800))
    16. 16. (defn transfer [from-account to-account amount] (dosync (if (> amount @from-account) (throw (Exception. "Not enough money!"))) (alter from-account - amount) (alter to-account + amount))) (def account-a (ref 1000)) (def account-b (ref 800)) (transfer account-a account-b 300) @account-a => 700
    17. 17. (defn transfer [from-account to-account amount] (dosync (if (> amount @from-account) (throw (Exception. "Not enough money!"))) (alter from-account - amount) (alter to-account + amount))) (def account-a (ref 1000)) (def account-b (ref 800)) (alter account-a - 100) => java.lang.IllegalStateException: No transaction running
    18. 18. The pragmatic programmers “Learn at least one new language every year”
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×