implementing stm in java
DESCRIPTION
Presentation for beginners. Explains some concurrency basics, how Software Transactional Memory (STM) works and some implementation details.TRANSCRIPT
![Page 1: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/1.jpg)
Implementing STM
Misha Kozik@mishadoff
![Page 2: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/2.jpg)
What is STM?
Software Transactional Memory
just another one concurrency control mechanism like locks or actors
![Page 3: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/3.jpg)
What is STM?
Software Transactional Memory
just another one concurrency control mechanism like locks or actors
Algorithm Database-likefor concurrency
![Page 4: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/4.jpg)
Database Transactions
Atomicity “all or nothing”
Consistency data is valid at the end
Isolation not affected by other txs
Durability ~persistence
![Page 5: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/5.jpg)
Database Transactions
Atomicity “all or nothing”
Consistency data is valid at the end
Isolation not affected by other txs
Durability ~persistence
Memory
![Page 6: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/6.jpg)
Bank Accounts Transferpublic class Account { private long money;
void add(long amount) { money += amount; }}
public class Bank { private Account[] accounts;
void transfer(Account a1, Account a2, int amount) { a1.add(-amount); a2.add(amount); }
public long sum() { long sum = 0; for (Account a : accounts) sum += a.getMoney(); }}
![Page 7: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/7.jpg)
Simulate Processpublic void simulate(int threads, int num) { ExecutorService service = Executors.newFixedThreadPool(threads); for (int i = 0; i < threads; i++) { service.submit(new BankThread(this, num)); } service.shutdown(); service.awaitTermination(1, TimeUnit.MINUTES);}
public class BankThread implements Runnable { private Bank bank; private int num;
public void run() { for (int i = 0; i < num; i++) { bank.transfer(bank.getRandomAccount(), bank.getRandomAccount(), bank.getRandomValue()); } }}
![Page 8: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/8.jpg)
Where is my money?!Bank bank = new Bank();System.out.println("Bank sum before: " + bank.sum());bank.simulate(100, 100000);System.out.println("Bank sum after: " + bank.sum());
Bank sum before: 10000000Bank sum after: 9970464
-20000$ = 49634
![Page 9: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/9.jpg)
How to solve it?
![Page 10: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/10.jpg)
synchronized
![Page 11: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/11.jpg)
What the difference?
public class Bank { synchronized void transfer(Account a1, Account a2, int amt) { a1.add(-amt); a2.add(amt); }}
public class Account { synchronized void transfer(Account a, int amt) { this.add(-amt); a.add(amt); }
synchronized void add(int amt) { value += amt; }}
VS
![Page 12: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/12.jpg)
synchronized: cons
→ no read/write distinction
→ slow/error-prone
→ low-level
→ protect code rather than data
![Page 13: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/13.jpg)
Locks
![Page 14: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/14.jpg)
still use locks in 2013RingBuffer buffer = null;readCpsLock.lock();try { if (ticks.containsKey(accountId)) { buffer = ticks.get(accountId); // check if this value changed if (buffer.getMaxCallCount() != cpsValue) { readCpsLock.unlock(); try {
writeCpsLock.lock(); try { ticks.remove(accountId); buffer = new RingBuffer(cpsValue, DEFAULT_TIME_UNIT); ticks.put(accountId, buffer); } finally { writeCpsLock.unlock(); }
} finally { readCpsLock.lock(); } } } else { buffer = new RingBuffer(cpsValue, DEFAULT_TIME_UNIT); readCpsLock.unlock(); try { writeCpsLock.lock(); try { ticks.put(accountId, buffer); } finally { writeCpsLock.unlock(); } } finally { readCpsLock.lock(); } }}finally { readCpsLock.unlock();}
useful code
![Page 15: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/15.jpg)
Locks: cons
→ tricky
→ error-prone
→ not composable
→ protect code rather than data
![Page 16: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/16.jpg)
Actors
![Page 17: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/17.jpg)
Actors in Erlang
ping(0, PID) -> PID ! finished, io:format("Ping stop~n", []);
ping(N, PID) -> PID ! {ping, self()}, receive pong -> io:format("Ping~n", []) end, ping(N - 1, PID).
pong() -> receive finished -> io:format("Pong stop~n", []); {ping, PID} -> io:format("Pong~n", []), PID ! pong, pong() end.
start() -> PID = spawn(pingpong, pong, []), spawn(pingpong, ping, [3, PID]).
![Page 18: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/18.jpg)
Actors: cons
→ code restructuring
→ deadlocks still possible
![Page 19: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/19.jpg)
STM
![Page 20: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/20.jpg)
STM in Clojure
(defn transfer [acc1 acc2 amount] (dosync (alter acc1 - amount) (alter acc2 + amount)))
(def account (ref 100))
![Page 21: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/21.jpg)
STM in Java
transaction { acc1.add(-value); acc2.add(value);}
![Page 22: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/22.jpg)
STM in Java
STM.transaction( new Runnable() { public void run() { acc1.add(-value); acc2.add(value); } });
![Page 23: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/23.jpg)
STM in Java 8
STM.transaction(() {→ acc1.add(-value); acc2.add(value);});
![Page 24: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/24.jpg)
STM: pros
→ natural approach
→ coordinated state
→ no deadlocks, no livelocks
![Page 25: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/25.jpg)
Implementing STM
![Page 26: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/26.jpg)
Intuition
→ start transaction
→ get ref snapshot
→ set of reads/writes* on snapshot
→ CAS initial and current snapshot
→ if CAS succeeds commit
→ else retry
![Page 27: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/27.jpg)
Ref v0.1
public final class Ref<T> { private T value;
public T getValue() { return value; }
public void setValue(T value) { this.value = value; }}
![Page 28: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/28.jpg)
Ref v0.1
public final class Ref<T> { private T value;
public T getValue() { return value; }
public void setValue(T value) { this.value = value; }}
// from anywhere
// from transaction
![Page 29: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/29.jpg)
Context
Transaction GlobalContext
singleton
<T> T get(Ref<T> ref);
<T> void set(Ref<T> ref, T value);
![Page 30: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/30.jpg)
Ref v0.2
public final class Ref<T> { private T value;
public T getValue(Context ctx) { return ctx.get(this); }
public void setValue(T value, Transaction tx) { tx.set(this, value); }}
![Page 31: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/31.jpg)
STM APIpublic final class STM { private STM() {}
public static void transaction(TransactionBlock block) { Transaction tx = new Transaction(); block.setTx(tx); block.run(); }
}
public abstract class TransactionBlock implements Runnable { private Transaction tx;
void setTx(Transaction tx) { this.tx = tx; }
public Transaction getTx() { return tx; }}
![Page 32: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/32.jpg)
STM APIpublic final class STM { private STM() {}
public static void transaction(TransactionBlock block) { Transaction tx = new Transaction(); block.setTx(tx); block.run(); }
}
public abstract class TransactionBlock implements Runnable { private Transaction tx;
void setTx(Transaction tx) { this.tx = tx; }
public Transaction getTx() { return tx; }}
NO return value (1)
![Page 33: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/33.jpg)
STM Usage
STM.transaction(new TransactionBlock() {
@Override public void run() { int old1 = a1.getValue(this.getTx()); a1.setValue(old1 - value, this.getTx()); int old2 = a2.getValue(this.getTx()); a2.setValue(old2 + value, this.getTx()); }
});
![Page 34: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/34.jpg)
STM Usage
STM.transaction(new TransactionBlock() {
@Override public void run() { int old1 = a1.getValue(this.getTx()); a1.setValue(old1 - value, this.getTx()); int old2 = a2.getValue(this.getTx()); a2.setValue(old2 + value, this.getTx()); }
});
What the mess? (2)
![Page 35: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/35.jpg)
GlobalContext v0.1
public class GlobalContext extends Context { private HashMap<Ref, Object> refs;
@Override <T> T get(Ref<T> ref) { return (T)refs.get(ref); }}
![Page 36: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/36.jpg)
GlobalContext v0.1
public class GlobalContext extends Context { private HashMap<Ref, Object> refs;
@Override <T> T get(Ref<T> ref) { return (T)refs.get(ref); }}
need control over ref mapcheat (3)
![Page 37: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/37.jpg)
Ref v0.3
public final class Ref<T> { private T value;
public T getValue(Context ctx) { return ctx.get(this); }
public void setValue(T value, Transaction tx) { tx.set(this, value); }}
![Page 38: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/38.jpg)
GlobalContext v0.2
public class GlobalContext extends Context { private HashMap<Ref, Object> refs;
@Override <T> T get(Ref<T> ref) { return ref.value; }}
![Page 39: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/39.jpg)
Transaction v0.1public final class Transaction extends Context { private HashMap<Ref, Object> inTxMap;
@Override <T> T get(Ref<T> ref) { if (!inTxMap.containsKey(ref)) { inTxMap.put(ref, ref.value); } return (T)inTxMap.get(ref); }
<T> void set(Ref<T> ref, T value) { inTxMap.put(ref, value); }}
![Page 40: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/40.jpg)
Transaction v0.1public final class Transaction extends Context { private HashMap<Ref, Object> inTxMap;
@Override <T> T get(Ref<T> ref) { if (!inTxMap.containsKey(ref)) { inTxMap.put(ref, ref.value); } return (T)inTxMap.get(ref); }
<T> void set(Ref<T> ref, T value) { inTxMap.put(ref, value); }}
NO Snapshot Isolation (4)
![Page 41: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/41.jpg)
Transaction v0.1public final class Transaction extends Context { private HashMap<Ref, Object> inTxMap;
@Override <T> T get(Ref<T> ref) { if (!inTxMap.containsKey(ref)) { inTxMap.put(ref, ref.value); } return (T)inTxMap.get(ref); }
<T> void set(Ref<T> ref, T value) { inTxMap.put(ref, value); }}
Separate reads & writes
![Page 42: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/42.jpg)
Transaction v0.2public final class Transaction extends Context { private HashMap<Ref, Object> inTxMap; private HashSet<Ref> toUpdate;
@Override <T> T get(Ref<T> ref) { if (!inTxMap.containsKey(ref)) { inTxMap.put(ref, ref.value); } return (T)inTxMap.get(ref); }
<T> void set(Ref<T> ref, T value) { inTxMap.put(ref, value); toUpdate.add(ref); }}
![Page 43: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/43.jpg)
Commitpublic final class Transaction extends Context { // …
void commit() { synchronized (STM.commitLock) { // TODO validate // TODO write values } }
} public final class STM { private STM() {}
public static Object commitLock = new Object();
// ...}
![Page 44: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/44.jpg)
Commit: Write Values
void commit() { synchronized (STM.commitLock) { // TODO validate for (Ref ref : toUpdate) { ref.value = inTxMap.get(ref); } } }
![Page 45: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/45.jpg)
Validation Idea
→ get all transaction-local refs
→ compare version with transaction revision
→ if all versions the same allow commit
→ else retry
![Page 46: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/46.jpg)
Ref v0.4
public final class Ref<T> { T value; long revision = 0;
// ...}
![Page 47: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/47.jpg)
Ref v0.4
public final class Ref<T> { T value; long revision = 0;
// ...}
No history (5)
![Page 48: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/48.jpg)
Transaction v0.3
public final class Transaction extends Context { // ...
private long revision; private static AtomicLong transactionNum = new AtomicLong(0);
Transaction() { revision = transactionNum.incrementAndGet(); }
// ...}
![Page 49: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/49.jpg)
Transaction v0.3
public final class Transaction extends Context { private HashMap<Ref, Long> version;
<T> T get(Ref<T> ref) { if (!inTxMap.containsKey(ref)) { inTxMap.put(ref, ref.value); if (!version.containsKey(ref)) { version.put(ref, ref.revision); } } return (T)inTxMap.get(ref); }
<T> void set(Ref<T> ref, T value) { inTxMap.put(ref, value); toUpdate.add(ref); if (!version.containsKey(ref)) { version.put(ref, ref.revision); } }}
![Page 50: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/50.jpg)
Commit: Validation
boolean commit() { synchronized (STM.commitLock) { boolean isValid = true; for (Ref ref : inTxMap.keySet()) { if (ref.revision != version.get(ref)) { isValid = false; break; } }
if (isValid) { for (Ref ref : toUpdate) { ref.value = inTxMap.get(ref); ref.revision = revision; } } return isValid; } }
![Page 51: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/51.jpg)
Commit: Validation
boolean commit() { synchronized (STM.commitLock) { boolean isValid = true; for (Ref ref : inTxMap.keySet()) { if (ref.revision != version.get(ref)) { isValid = false; break; } }
if (isValid) { for (Ref ref : toUpdate) { ref.value = inTxMap.get(ref); ref.revision = revision; } } return isValid; } }
![Page 52: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/52.jpg)
Commit: Validation
boolean commit() { synchronized (STM.commitLock) { boolean isValid = true; for (Ref ref : inTxMap.keySet()) { if (ref.revision != version.get(ref)) { isValid = false; break; } }
if (isValid) { for (Ref ref : toUpdate) { ref.value = inTxMap.get(ref); ref.revision = revision; } } return isValid; } } Transaction revision
![Page 53: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/53.jpg)
Commit: Validation
boolean commit() { synchronized (STM.commitLock) { boolean isValid = true; for (Ref ref : inTxMap.keySet()) { if (ref.revision != version.get(ref)) { isValid = false; break; } }
if (isValid) { for (Ref ref : toUpdate) { ref.value = inTxMap.get(ref); ref.revision = revision; } } return isValid; } }
![Page 54: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/54.jpg)
STM Transaction
public final class STM { private STM() {}
public static Object commitLock = new Object();
public static void transaction(TransactionBlock block) { boolean committed = false; while (!committed) { Transaction tx = new Transaction(); block.setTx(tx); block.run(); committed = tx.commit(); } }
}
![Page 55: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/55.jpg)
STM Transaction
public final class STM { private STM() {}
public static Object commitLock = new Object();
public static void transaction(TransactionBlock block) { boolean committed = false; while (!committed) { Transaction tx = new Transaction(); block.setTx(tx); block.run(); committed = tx.commit(); } }
}No nested
transactions (7)No exceptions handling (6)
![Page 56: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/56.jpg)
![Page 57: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/57.jpg)
What the problem?
boolean commit() { synchronized (STM.commitLock) { // ... if (isValid) { for (Ref ref : toUpdate) { ref.value = inTxMap.get(ref); ref.revision = revision; } } // ... }}
![Page 58: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/58.jpg)
What the problem?
boolean commit() { synchronized (STM.commitLock) { // ... if (isValid) { for (Ref ref : toUpdate) { ref.value = inTxMap.get(ref); ref.revision = revision; } } // ... }}
Memory switch is atomic
Two Memory switches are not atomic
![Page 59: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/59.jpg)
RefTuple
public class RefTuple<V, R> { V value; R revision;
public RefTuple(V v, R r) { this.value = v; this.revision = r; }
static <V, R> RefTuple get(V v, R r) { return new RefTuple<V, R>(v, r); }}
![Page 60: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/60.jpg)
Ref v0.5
public final class Ref<T> { RefTuple<T, Long> content;
public Ref(T value) { content = RefTuple.get(value, 0); }
// ...}
![Page 61: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/61.jpg)
Transaction.commit()
for (Ref ref : toUpdate) { ref.value = inTxMap.get(ref); ref.revision = revision;}
for (Ref ref : toUpdate) { ref.content = RefTuple.get(inTxMap.get(ref), revision);}
![Page 62: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/62.jpg)
Transaction.get()
<T> T get(Ref<T> ref) { if (!inTxMap.containsKey(ref)) { inTxMap.put(ref, ref.value); if (!version.containsKey(ref)) { version.put(ref, ref.revision); } } return (T)inTxMap.get(ref);}
<T> T get(Ref<T> ref) { if (!inTxMap.containsKey(ref)) { RefTuple<T, Long> tuple = ref.content; inTxMap.put(ref, tuple.value); if (!version.containsKey(ref)) { version.put(ref, tuple.revision); } } return (T)inTxMap.get(ref);}
2 non-sync reads
![Page 63: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/63.jpg)
// TODO
1. Support return value in TX2. Avoid this.getTx() repetition3. Fair GlobalContext4. Snapshot Isolation5. Support ref history6. Support exceptions7. Support nested transactions
![Page 64: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/64.jpg)
STM Algorithms
Multi-Version Concurrency Control
Lazy Snapshot Algorithm
Transactional Locking 2
![Page 65: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/65.jpg)
Practical Advices
→ avoid side-effects
→ avoid short/long transactions
→ separate as much as possible outside of transaction
→ ref value must be immutable
OR STM WON'T HELP YOU
![Page 66: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/66.jpg)
“But STM is slow...”
![Page 67: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/67.jpg)
TM/GC Analogy
Transactional Memory is to shared-memory concurrency
as
Garbage Collection is to memory management.
![Page 68: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/68.jpg)
→ atomics
→ immutability
→ avoid shared state
→ lock-free data structures
Non-STM
![Page 69: Implementing STM in Java](https://reader033.vdocuments.us/reader033/viewer/2022052618/554f8313b4c905435d8b4ab3/html5/thumbnails/69.jpg)
Links
→ STM In Clojure
→ Locks, Actors and STM in pictures
→ The Dining Philosophers Problem
→ Clojure refs
→ TM/GC Analogy [PDF]
→ STM in Scala
→ 7 Concurrency Models in 7 weeks