SlideShare une entreprise Scribd logo
1  sur  69
Télécharger pour lire hors ligne
Implementing STM

Misha Kozik

@mishadoff
What is STM?
S oftware T ransactional M emory

just another one
concurrency control mechanism
like locks or actors
What is STM?
S oftware T ransactional M emory
Algorithm for

Database-like concurrency

just another one
concurrency control mechanism
like locks or actors
Database Transactions

A tomicity
C onsistency
I solation
D urability

“all or nothing”
data is valid at the end
not affected by other txs
~persistence
Memory
Database Transactions

A tomicity
C onsistency
I solation
D urability

“all or nothing”
data is valid at the end
not affected by other txs
~persistence
Bank Accounts Transfer
public 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();
}
Simulate Process
public 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());
}
}
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:
Bank sum after:

10000000
9970464

-20000$ =

49634
How to solve it?
synchronized
What the difference?
public class Bank {
synchronized void transfer(Account a1, Account a2, int amt) {
a1.add(-amt);
a2.add(amt);
}
}

VS
public class Account {
synchronized void transfer(Account a, int amt) {
this.add(-amt);
a.add(amt);
}

}

synchronized void add(int amt) {
value += amt;
}
synchronized: cons
→ no read/write distinction
→ slow/error-prone
→ low-level
→ protect code rather than data
Locks
still use locks in 2013
RingBuffer 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
Locks: cons
→ tricky
→ error-prone
→ not composable
→ protect code rather than data
Actors
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]).
Actors: cons
→ code restructuring
→ deadlocks still possible
STM
STM in Clojure
(def account (ref 100))

(defn transfer [acc1 acc2 amount]
(dosync
(alter acc1 - amount)
(alter acc2 + amount)))
STM in Java

transaction {
acc1.add(-value);
acc2.add(value);
}
STM in Java
STM.transaction(
new Runnable() {
public void run() {
acc1.add(-value);
acc2.add(value);
}
});
STM in Java 8
STM.transaction(() → {
acc1.add(-value);
acc2.add(value);
});
STM: pros
→ natural approach
→ coordinated state
→ no deadlocks, no livelocks
Implementing STM
Intuition
→ start transaction
→ get ref snapshot
→ set of reads/writes* on snapshot
→ CAS initial and current snapshot
→ if CAS succeeds commit
→ else retry
Ref v0.1
public final class Ref<T> {
private T value;
public T getValue() {
return value;
}

}

public void setValue(T value) {
this.value = value;
}
Ref v0.1
public final class Ref<T> {
private T value;
public T getValue() {
return value;
}

}

// from anywhere

public void setValue(T value) {
this.value = value;
}
// from transaction
Context

Transaction
<T> void set(Ref<T> ref, T value);

<T> T get(Ref<T> ref);

GlobalContext
singleton
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);
}
}
STM API
public 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;
}
STM API
public final class STM {
private STM() {}
public static void transaction(TransactionBlock block) {
Transaction tx = new Transaction();
block.setTx(tx);
block.run();
}
NO return value (1)
}
public abstract class TransactionBlock implements Runnable {
private Transaction tx;
void setTx(Transaction tx) {
this.tx = tx;
}

}

public Transaction getTx() {
return tx;
}
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());
}
});
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)
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);
}
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 map
cheat (3)
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);
}
}
GlobalContext v0.2

public class GlobalContext extends Context {
private HashMap<Ref, Object> refs;

}

@Override
<T> T get(Ref<T> ref) {
return ref.value;
}
Transaction v0.1
public 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);
}
Transaction v0.1
public final class Transaction extends Context {
private HashMap<Ref, Object> inTxMap;
NO Snapshot Isolation (4)
@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);
}
Transaction v0.1
public final class Transaction extends Context {
private HashMap<Ref, Object> inTxMap;
Separate reads
@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);
}

& writes
Transaction v0.2
public 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);
}
Commit
public 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();
}

// ...
Commit: Write Values
void commit() {
synchronized (STM.commitLock) {
// TODO validate
for (Ref ref : toUpdate) {
ref.value = inTxMap.get(ref);
}
}
}
Validation Idea
→ get all transaction-local refs
→ compare version with transaction
revision
→ if all versions the same
allow commit
→ else retry
Ref v0.4
public final class Ref<T> {
T value;
long revision = 0;
// ...
}
Ref v0.4
public final class Ref<T> {
T value;
long revision = 0;
// ...
}
No history (5)
Transaction v0.3
public final class Transaction extends Context {
// ...
private long revision;
private static AtomicLong transactionNum =
new AtomicLong(0);
Transaction() {
revision = transactionNum.incrementAndGet();
}
// ...
}
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);
}
}
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;
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;
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
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;
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();
}
}
}
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 exceptions
handling (6)

No nested
transactions (7)
What the problem?
boolean commit() {
synchronized (STM.commitLock) {
// ...
if (isValid) {
for (Ref ref : toUpdate) {
ref.value = inTxMap.get(ref);
ref.revision = revision;
}
}
// ...
}
}
What the problem?
Memory switch is atomic

boolean commit() {
synchronized (STM.commitLock) {
// ...
if (isValid) {
for (Ref ref : toUpdate) {
ref.value = inTxMap.get(ref);
ref.revision = revision;
}
}
// ...
}
Two Memory switches
}
are not atomic
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);
}
}
Ref v0.5
public final class Ref<T> {
RefTuple<T, Long> content;
public Ref(T value) {
content = RefTuple.get(value, 0);
}
// ...
}
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);
}
Transaction.get()
<T> T get(Ref<T> ref) {
2 non-sync reads
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);
}
// TODO
1.
2.
3.
4.
5.
6.
7.

Support return value in TX
Avoid this.getTx() repetition
Fair GlobalContext
Snapshot Isolation
Support ref history
Support exceptions
Support nested transactions
STM Algorithms
Multi-Version Concurrency Control
Lazy Snapshot Algorithm
Transactional Locking 2
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
“But STM is slow...”
TM/GC

Analogy

Transactional Memory is to
shared-memory concurrency

as
Garbage Collection is to
memory management.
Non-STM

→ atomics
→ immutability
→ avoid shared state
→ lock-free data structures
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

Contenu connexe

En vedette

Crafting a Ready-to-Go STM
Crafting  a Ready-to-Go STMCrafting  a Ready-to-Go STM
Crafting a Ready-to-Go STMGuy Korland
 
Closures: The Next "Big Thing" In Java
Closures: The Next "Big Thing" In JavaClosures: The Next "Big Thing" In Java
Closures: The Next "Big Thing" In JavaRussel Winder
 
実世界Live Programmingの実現に向けて
実世界Live Programmingの実現に向けて実世界Live Programmingの実現に向けて
実世界Live Programmingの実現に向けてJun Kato
 
Adaptive Thread Scheduling Techniques for Improving Scalability of Software T...
Adaptive Thread Scheduling Techniques for Improving Scalability of Software T...Adaptive Thread Scheduling Techniques for Improving Scalability of Software T...
Adaptive Thread Scheduling Techniques for Improving Scalability of Software T...Kinson Chan
 
Multi-core Parallelization in Clojure - a Case Study
Multi-core Parallelization in Clojure - a Case StudyMulti-core Parallelization in Clojure - a Case Study
Multi-core Parallelization in Clojure - a Case Studyelliando dias
 
Intro to Java 8 Closures (Dainius Mezanskas)
Intro to Java 8 Closures (Dainius Mezanskas)Intro to Java 8 Closures (Dainius Mezanskas)
Intro to Java 8 Closures (Dainius Mezanskas)Kaunas Java User Group
 
Optimizing STM Content Spend & Improving Access by Re-Engineering Workflows
Optimizing STM Content Spend & Improving Access by Re-Engineering WorkflowsOptimizing STM Content Spend & Improving Access by Re-Engineering Workflows
Optimizing STM Content Spend & Improving Access by Re-Engineering WorkflowsIan Palmer
 
STM Spring Meeting Collexis Overview April 2009
STM Spring Meeting  Collexis   Overview April 2009STM Spring Meeting  Collexis   Overview April 2009
STM Spring Meeting Collexis Overview April 2009Darrell W. Gunter
 
STM in Liquids - a scanning tunnelling microscopy exploration of the liquid-s...
STM in Liquids - a scanning tunnelling microscopy exploration of the liquid-s...STM in Liquids - a scanning tunnelling microscopy exploration of the liquid-s...
STM in Liquids - a scanning tunnelling microscopy exploration of the liquid-s...bhulsken
 
Imaging, spectroscopy and manipulation of C60 molecule on semiconductor surf...
 Imaging, spectroscopy and manipulation of C60 molecule on semiconductor surf... Imaging, spectroscopy and manipulation of C60 molecule on semiconductor surf...
Imaging, spectroscopy and manipulation of C60 molecule on semiconductor surf...Cristina Chiutu
 
[Java concurrency]02.basic thread synchronization
[Java concurrency]02.basic thread synchronization[Java concurrency]02.basic thread synchronization
[Java concurrency]02.basic thread synchronizationxuehan zhu
 
pick and place robotic arm
pick and place robotic armpick and place robotic arm
pick and place robotic armANJANA ANILKUMAR
 
Go Reactive: Event-Driven, Scalable, Resilient & Responsive Systems
Go Reactive: Event-Driven, Scalable, Resilient & Responsive SystemsGo Reactive: Event-Driven, Scalable, Resilient & Responsive Systems
Go Reactive: Event-Driven, Scalable, Resilient & Responsive SystemsJonas Bonér
 
On heap cache vs off-heap cache
On heap cache vs off-heap cacheOn heap cache vs off-heap cache
On heap cache vs off-heap cachergrebski
 
Pick and place Line following robot report
Pick and place Line following robot reportPick and place Line following robot report
Pick and place Line following robot reportPradeep Yadav
 
pick-and-place-robot
pick-and-place-robotpick-and-place-robot
pick-and-place-robotSuchit Moon
 

En vedette (20)

Crafting a Ready-to-Go STM
Crafting  a Ready-to-Go STMCrafting  a Ready-to-Go STM
Crafting a Ready-to-Go STM
 
Closures: The Next "Big Thing" In Java
Closures: The Next "Big Thing" In JavaClosures: The Next "Big Thing" In Java
Closures: The Next "Big Thing" In Java
 
実世界Live Programmingの実現に向けて
実世界Live Programmingの実現に向けて実世界Live Programmingの実現に向けて
実世界Live Programmingの実現に向けて
 
Adaptive Thread Scheduling Techniques for Improving Scalability of Software T...
Adaptive Thread Scheduling Techniques for Improving Scalability of Software T...Adaptive Thread Scheduling Techniques for Improving Scalability of Software T...
Adaptive Thread Scheduling Techniques for Improving Scalability of Software T...
 
Multi-core Parallelization in Clojure - a Case Study
Multi-core Parallelization in Clojure - a Case StudyMulti-core Parallelization in Clojure - a Case Study
Multi-core Parallelization in Clojure - a Case Study
 
Intro to Java 8 Closures (Dainius Mezanskas)
Intro to Java 8 Closures (Dainius Mezanskas)Intro to Java 8 Closures (Dainius Mezanskas)
Intro to Java 8 Closures (Dainius Mezanskas)
 
Optimizing STM Content Spend & Improving Access by Re-Engineering Workflows
Optimizing STM Content Spend & Improving Access by Re-Engineering WorkflowsOptimizing STM Content Spend & Improving Access by Re-Engineering Workflows
Optimizing STM Content Spend & Improving Access by Re-Engineering Workflows
 
STM Spring Meeting Collexis Overview April 2009
STM Spring Meeting  Collexis   Overview April 2009STM Spring Meeting  Collexis   Overview April 2009
STM Spring Meeting Collexis Overview April 2009
 
STM in Liquids - a scanning tunnelling microscopy exploration of the liquid-s...
STM in Liquids - a scanning tunnelling microscopy exploration of the liquid-s...STM in Liquids - a scanning tunnelling microscopy exploration of the liquid-s...
STM in Liquids - a scanning tunnelling microscopy exploration of the liquid-s...
 
Imaging, spectroscopy and manipulation of C60 molecule on semiconductor surf...
 Imaging, spectroscopy and manipulation of C60 molecule on semiconductor surf... Imaging, spectroscopy and manipulation of C60 molecule on semiconductor surf...
Imaging, spectroscopy and manipulation of C60 molecule on semiconductor surf...
 
[Java concurrency]02.basic thread synchronization
[Java concurrency]02.basic thread synchronization[Java concurrency]02.basic thread synchronization
[Java concurrency]02.basic thread synchronization
 
253283568 stm
253283568 stm253283568 stm
253283568 stm
 
Sem2 robotics ppt
Sem2 robotics pptSem2 robotics ppt
Sem2 robotics ppt
 
pick and place robotic arm
pick and place robotic armpick and place robotic arm
pick and place robotic arm
 
Go Reactive: Event-Driven, Scalable, Resilient & Responsive Systems
Go Reactive: Event-Driven, Scalable, Resilient & Responsive SystemsGo Reactive: Event-Driven, Scalable, Resilient & Responsive Systems
Go Reactive: Event-Driven, Scalable, Resilient & Responsive Systems
 
On heap cache vs off-heap cache
On heap cache vs off-heap cacheOn heap cache vs off-heap cache
On heap cache vs off-heap cache
 
DSL in Clojure
DSL in ClojureDSL in Clojure
DSL in Clojure
 
Pick and place Line following robot report
Pick and place Line following robot reportPick and place Line following robot report
Pick and place Line following robot report
 
pick-and-place-robot
pick-and-place-robotpick-and-place-robot
pick-and-place-robot
 
Matlab GUI
Matlab GUIMatlab GUI
Matlab GUI
 

Similaire à Implementing STM in Java

Deuce STM - CMP'09
Deuce STM - CMP'09Deuce STM - CMP'09
Deuce STM - CMP'09Guy Korland
 
help me Java projectI put problem and my own code in the linkmy .pdf
help me Java projectI put problem and my own code in the linkmy .pdfhelp me Java projectI put problem and my own code in the linkmy .pdf
help me Java projectI put problem and my own code in the linkmy .pdfarihantmum
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Juan Pablo
 
Software Transactioneel Geheugen
Software Transactioneel GeheugenSoftware Transactioneel Geheugen
Software Transactioneel GeheugenDevnology
 
C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴명신 김
 
Java Concurrency Idioms
Java Concurrency IdiomsJava Concurrency Idioms
Java Concurrency IdiomsAlex Miller
 
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMMario Fusco
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy codeShriKant Vashishtha
 
Advanced Java - Practical File
Advanced Java - Practical FileAdvanced Java - Practical File
Advanced Java - Practical FileFahad Shaikh
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaFrank Lyaruu
 
Programming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdf
Programming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdfProgramming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdf
Programming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdfssuser6254411
 
Deep dumpster diving 2010
Deep dumpster diving 2010Deep dumpster diving 2010
Deep dumpster diving 2010RonnBlack
 
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...julien.ponge
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestPavan Chitumalla
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Paco de la Cruz
 
Concurrency in Programming Languages
Concurrency in Programming LanguagesConcurrency in Programming Languages
Concurrency in Programming LanguagesYudong Li
 

Similaire à Implementing STM in Java (20)

Deuce STM - CMP'09
Deuce STM - CMP'09Deuce STM - CMP'09
Deuce STM - CMP'09
 
help me Java projectI put problem and my own code in the linkmy .pdf
help me Java projectI put problem and my own code in the linkmy .pdfhelp me Java projectI put problem and my own code in the linkmy .pdf
help me Java projectI put problem and my own code in the linkmy .pdf
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#
 
Software Transactioneel Geheugen
Software Transactioneel GeheugenSoftware Transactioneel Geheugen
Software Transactioneel Geheugen
 
Thread
ThreadThread
Thread
 
C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴
 
Java Concurrency Idioms
Java Concurrency IdiomsJava Concurrency Idioms
Java Concurrency Idioms
 
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
Advanced Java - Practical File
Advanced Java - Practical FileAdvanced Java - Practical File
Advanced Java - Practical File
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
 
Programming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdf
Programming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdfProgramming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdf
Programming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdf
 
Deep dumpster diving 2010
Deep dumpster diving 2010Deep dumpster diving 2010
Deep dumpster diving 2010
 
Ss
SsSs
Ss
 
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
 
Anti patterns
Anti patternsAnti patterns
Anti patterns
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)
 
Concurrency in Programming Languages
Concurrency in Programming LanguagesConcurrency in Programming Languages
Concurrency in Programming Languages
 

Plus de Misha Kozik

Plus de Misha Kozik (6)

QBIC
QBICQBIC
QBIC
 
Writing DSL in Clojure
Writing DSL in ClojureWriting DSL in Clojure
Writing DSL in Clojure
 
Sentiments Improvement
Sentiments ImprovementSentiments Improvement
Sentiments Improvement
 
Timezone Mess
Timezone MessTimezone Mess
Timezone Mess
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Intro
 
Unsafe Java
Unsafe JavaUnsafe Java
Unsafe Java
 

Dernier

DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontologyjohnbeverley2021
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Angeliki Cooney
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Jeffrey Haguewood
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityWSO2
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 

Dernier (20)

DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 

Implementing STM in Java

  • 2. What is STM? S oftware T ransactional M emory just another one concurrency control mechanism like locks or actors
  • 3. What is STM? S oftware T ransactional M emory Algorithm for Database-like concurrency just another one concurrency control mechanism like locks or actors
  • 4. Database Transactions A tomicity C onsistency I solation D urability “all or nothing” data is valid at the end not affected by other txs ~persistence
  • 5. Memory Database Transactions A tomicity C onsistency I solation D urability “all or nothing” data is valid at the end not affected by other txs ~persistence
  • 6. Bank Accounts Transfer public 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(); }
  • 7. Simulate Process public 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()); } }
  • 8. 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: Bank sum after: 10000000 9970464 -20000$ = 49634
  • 11. What the difference? public class Bank { synchronized void transfer(Account a1, Account a2, int amt) { a1.add(-amt); a2.add(amt); } } VS public class Account { synchronized void transfer(Account a, int amt) { this.add(-amt); a.add(amt); } } synchronized void add(int amt) { value += amt; }
  • 12. synchronized: cons → no read/write distinction → slow/error-prone → low-level → protect code rather than data
  • 13. Locks
  • 14. still use locks in 2013 RingBuffer 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
  • 15. Locks: cons → tricky → error-prone → not composable → protect code rather than data
  • 17. 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]).
  • 18. Actors: cons → code restructuring → deadlocks still possible
  • 19. STM
  • 20. STM in Clojure (def account (ref 100)) (defn transfer [acc1 acc2 amount] (dosync (alter acc1 - amount) (alter acc2 + amount)))
  • 21. STM in Java transaction { acc1.add(-value); acc2.add(value); }
  • 22. STM in Java STM.transaction( new Runnable() { public void run() { acc1.add(-value); acc2.add(value); } });
  • 23. STM in Java 8 STM.transaction(() → { acc1.add(-value); acc2.add(value); });
  • 24. STM: pros → natural approach → coordinated state → no deadlocks, no livelocks
  • 26. Intuition → start transaction → get ref snapshot → set of reads/writes* on snapshot → CAS initial and current snapshot → if CAS succeeds commit → else retry
  • 27. Ref v0.1 public final class Ref<T> { private T value; public T getValue() { return value; } } public void setValue(T value) { this.value = value; }
  • 28. Ref v0.1 public final class Ref<T> { private T value; public T getValue() { return value; } } // from anywhere public void setValue(T value) { this.value = value; } // from transaction
  • 29. Context Transaction <T> void set(Ref<T> ref, T value); <T> T get(Ref<T> ref); GlobalContext singleton
  • 30. 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); } }
  • 31. STM API public 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; }
  • 32. STM API public final class STM { private STM() {} public static void transaction(TransactionBlock block) { Transaction tx = new Transaction(); block.setTx(tx); block.run(); } NO return value (1) } public abstract class TransactionBlock implements Runnable { private Transaction tx; void setTx(Transaction tx) { this.tx = tx; } } public Transaction getTx() { return tx; }
  • 33. 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()); } });
  • 34. 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)
  • 35. 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); }
  • 36. 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 map cheat (3)
  • 37. 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); } }
  • 38. GlobalContext v0.2 public class GlobalContext extends Context { private HashMap<Ref, Object> refs; } @Override <T> T get(Ref<T> ref) { return ref.value; }
  • 39. Transaction v0.1 public 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); }
  • 40. Transaction v0.1 public final class Transaction extends Context { private HashMap<Ref, Object> inTxMap; NO Snapshot Isolation (4) @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); }
  • 41. Transaction v0.1 public final class Transaction extends Context { private HashMap<Ref, Object> inTxMap; Separate reads @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); } & writes
  • 42. Transaction v0.2 public 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); }
  • 43. Commit public 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(); } // ...
  • 44. Commit: Write Values void commit() { synchronized (STM.commitLock) { // TODO validate for (Ref ref : toUpdate) { ref.value = inTxMap.get(ref); } } }
  • 45. Validation Idea → get all transaction-local refs → compare version with transaction revision → if all versions the same allow commit → else retry
  • 46. Ref v0.4 public final class Ref<T> { T value; long revision = 0; // ... }
  • 47. Ref v0.4 public final class Ref<T> { T value; long revision = 0; // ... } No history (5)
  • 48. Transaction v0.3 public final class Transaction extends Context { // ... private long revision; private static AtomicLong transactionNum = new AtomicLong(0); Transaction() { revision = transactionNum.incrementAndGet(); } // ... }
  • 49. 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); } }
  • 50. 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;
  • 51. 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;
  • 52. 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
  • 53. 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;
  • 54. 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(); } } }
  • 55. 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 exceptions handling (6) No nested transactions (7)
  • 56.
  • 57. What the problem? boolean commit() { synchronized (STM.commitLock) { // ... if (isValid) { for (Ref ref : toUpdate) { ref.value = inTxMap.get(ref); ref.revision = revision; } } // ... } }
  • 58. What the problem? Memory switch is atomic boolean commit() { synchronized (STM.commitLock) { // ... if (isValid) { for (Ref ref : toUpdate) { ref.value = inTxMap.get(ref); ref.revision = revision; } } // ... } Two Memory switches } are not atomic
  • 59. 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); } }
  • 60. Ref v0.5 public final class Ref<T> { RefTuple<T, Long> content; public Ref(T value) { content = RefTuple.get(value, 0); } // ... }
  • 61. 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); }
  • 62. Transaction.get() <T> T get(Ref<T> ref) { 2 non-sync reads 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); }
  • 63. // TODO 1. 2. 3. 4. 5. 6. 7. Support return value in TX Avoid this.getTx() repetition Fair GlobalContext Snapshot Isolation Support ref history Support exceptions Support nested transactions
  • 64. STM Algorithms Multi-Version Concurrency Control Lazy Snapshot Algorithm Transactional Locking 2
  • 65. 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
  • 66. “But STM is slow...”
  • 67. TM/GC Analogy Transactional Memory is to shared-memory concurrency as Garbage Collection is to memory management.
  • 68. Non-STM → atomics → immutability → avoid shared state → lock-free data structures
  • 69. 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

Notes de l'éditeur

  1. {}