concurrent programming without synchronization

Post on 13-Apr-2017

146 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

1CONFIDENTIAL

CONCURRENT PROGRAMMING

WITHOUT SYNCHRONIZATION

JENI MARKISHKA

MARTIN HRISTOVJULY 4, 2015

2CONFIDENTIAL

THREAD SAFETY?

WHAT IS

3CONFIDENTIAL

THREAD SAFETY

• … is unfortunately hard to be

defined.

• Because it means different things to

different people!

• Brian Goetz:

• A class is thread-safe when it continues to behave

correctly when accessed from multiple threads.

• Joseph Albahari:

• A program or method is thread-safe if it has no

indeterminacy in the face of any multithreading

scenario.

Image credit: http://www.beaconhillnw.com/2014/09/workplace-safety-signage/

4CONFIDENTIAL

ALL ABOUT DATA INTEGRITY!

THREAD SAFETY IS

5CONFIDENTIAL

THREAD SAFETY?

BUT HOW DO WE ACHIEVE

6CONFIDENTIAL

THREAD SAFETY?

BUT HOW DO WE ACHIEVE

> MUTEXES

> LOCK-FREE MECHANISMS

7CONFIDENTIAL

LOCK-FREE THREAD SAFETY

Immutability1

Compare-And-Swap (CAS)2

volatile piggy-backing3

Thread confinement4

• Ad-hoc Thread Confinement

• Stack Confinement

• Thread Confinement with ThreadLocal

8CONFIDENTIAL

IMMUTABILITY

• Immutable objects cannot change their state once constructed

• Strategy for definition:

• No setter methods

• All fields private and final

• No methods overriding allowed

• No this and mutable field references escapes

• Thread safety guaranteed by initialization safety (JSR-133)

• Safe and simple; consider whenever feasible

Image credit: https://www.flickr.com/photos/bala_/4184518104/

9CONFIDENTIAL

@ThreadSafepublic final class CreditCard {

private final String holder;private final String number;

public CreditCard(String holder,String number) {

this.holder = holder;this.number = number;

}

public String getHolder() {return holder;

}

public String getNumber() {return number;

}}

THREAD-SAFE

IMMUTABILITY (EXAMPLES)

NOT THREAD-SAFE

@NotThreadSafefinal public class ShoppingCart {

private CartService cartService;private final List<Item> items;

@Autowiredpublic ShoppingCart(List<Item> items,

CartService cs) {cartService = cs;cartService.registerCart(this);this.items = Collections

.unmodifiableList(items);}

public List<Item> getItems() {return items;

}}

10CONFIDENTIAL

@ThreadSafepublic final class CreditCard {

private final String holder;private final String number;

public CreditCard(String holder,String number) {

this.holder = holder;this.number = number;

}

public String getHolder() {return holder;

}

public String getNumber() {return number;

}}

THREAD-SAFE

IMMUTABILITY (EXAMPLES)

NOT THREAD-SAFE

@NotThreadSafefinal public class ShoppingCart {

private CartService cartService;private final List<Item> items;

@Autowiredpublic ShoppingCart(List<Item> items,

CartService cs) {cartService = cs;cartService.registerCart(this);this.items = Collections

.unmodifiableList(items);}

public List<Item> getItems() {return items;

}} Escape of mutable data object reference

Escape of this reference during construction

11CONFIDENTIAL

EFFECTIVE IMMUTABILITY

• A special case of immutability

• Effective immutability is a

characteristic of instances rather

than classes

• An object instance that cannot be

mutated via any execution path is

effectively immutable

• Effectively immutable objects are

instances of mutable classes

Image credit: https://www.flickr.com/photos/pupski/34237242/

12CONFIDENTIAL

@NotThreadSafepublic final class AirConditioner {

private final boolean canChange;private short temperature;

public AirConditioner(short temperature, boolean canChange) {this.canChange = canChange;this.temperature = temperature;

}

public void setTemperature(short newTemperature) {if (canChange) {

temperature = newTemperature;} else {

throw new IllegalStateException();}

}

public short getTemperature() {return temperature;

}}

EFFECTIVE IMMUTABILITY (EXAMPLE)

THREAD-SAFE INSTANCE

AirConditioner airConditioner =

new AirConditioner(24, false);

13CONFIDENTIAL

@NotThreadSafepublic final class AirConditioner {

private final boolean canChange;private short temperature;

public AirConditioner(short temperature, boolean canChange) {this.canChange = canChange;this.temperature = temperature;

}

public void setTemperature(short newTemperature) {if (canChange) {

temperature = newTemperature;} else {

throw new IllegalStateException();}

}

public short getTemperature() {return temperature;

}}

EFFECTIVE IMMUTABILITY (EXAMPLE)

THREAD-SAFE INSTANCE

AirConditioner airConditioner =

new AirConditioner(24, false);

14CONFIDENTIAL

COMPARE-AND-SWAP (CAS)

• Non-blocking algorithm for concurrent access to shared data

• Modifies a value in memory only if it is equal to a given value, otherwise the modification fails

• Ensures that the new value is calculated based on up-to-date data

• Uses atomic CPU instructions:• CMPXCHG (x86)• CMPXCHGQ (x64)

• Available via atomic variables in Java 5.0+ java.util.concurrent.atomic

Image credit: http://www.keepcalm-o-matic.co.uk/

15CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

CPU2

16CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

CPU2

read

17CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

21

CPU2

read

21

18CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

21

CPU2

19CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

21

CPU2

read

20CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

21

CPU2

21

read

ok

21CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

21

CPU2

21

22CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

21

CPU2

2122

23CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

22

CPU2

21

cas(21,22)

24CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

21

CPU2

21

cas(21,22)

22

ok

2222

25CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

21

CPU2

21

22

2222

22

26CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

21

CPU2

21

22

2222

22

20

27CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

21

CPU2

21

22

2222

22

20

cas(21,20)

28CONFIDENTIAL

CPU1

CAS EXPLAINED

MEMORY

21

21

CPU2

21

22

2222

22

20

cas(21,20)

write

failed

29CONFIDENTIAL

@ThreadSafepublic class AtomicCounter {

private final AtomicInteger value =new AtomicInteger(0);

public int getValue() {return value.get();

}

public int increment() {return value.incrementAndGet();

}}

THREAD-SAFE

CAS vs volatile (EXAMPLES)

NOT THREAD-SAFE

@NotThreadSafepublic class VolatileCounter {

private volatile int value = 0;

public int getValue() {return value;

}

public int increment() {return value++;

}}

30CONFIDENTIAL

@ThreadSafepublic class AtomicCounter {

private final AtomicInteger value =new AtomicInteger(0);

public int getValue() {return value.get();

}

public int increment() {return value.incrementAndGet();

}}

THREAD-SAFE

CAS vs volatile (EXAMPLES)

NOT THREAD-SAFE

@NotThreadSafepublic class VolatileCounter {

private volatile int value = 0;

public int getValue() {return value;

}

public int increment() {return value++;

}} • Unsafe operation

• The increment operator is not an

atomic action:

• Read value

• Increment by 1

• Write value

• Volatile ensures visibility only and not

atomicity

31CONFIDENTIAL

@ThreadSafepublic class VolatileCounter {

private volatile int value = 0;

public int getValue() {return value;

}

public synchronized int increment() {return value++;

}}

@ThreadSafepublic class AtomicCounter {

private final AtomicInteger value =new AtomicInteger(0);

public int getValue() {return value.get();

}

public int increment() {return value.incrementAndGet();

}}

THREAD-SAFE

CAS vs volatile (EXAMPLES)

THREAD-SAFE

Lock contention == performance degradation

32CONFIDENTIAL

VOLATILE PIGGY-BACKING

• Allows volatile-like semantics for non-volatile variables

• Exploits the happens-before order established by JSR-133

• Actions in the same thread cannot be reordered (Program order)

• A write to a volatile field

happens-before every

subsequent read of that field

• Volatile writes effectively

create a memory fence

which flushes CPU cache

Image credit: http://www.magic-of-color.com/?p=2127

33CONFIDENTIAL

public class Point {

private int x;private int y;

private volatile boolean done = false;

public void calculateCoordinates() {x = someHeavyweightAlgorithm(…); // x=5y = someHeavyweightAlgorithm(…); // y=10sync();

}

private void sync() {done = true;

}

public int getX() { return x; }public int getY() { return y; }public boolean isDone() { return done; }

}

THREAD #1

VOLATILE PIGGY-BACKING (EXAMPLE)

THREAD #2

public class CoordinatesConsumer {private Point point;

public CoordinatesConsumer(Point point) {this.point = point;

}

public void doSomething() {while (!point.isDone()) ; // Busy waitint x = point.getX(); // x=5int y = point.getY(); // y=10

}}

• x and y get visible in Thread #2 even

though they are not volatile

• they piggyback on done which is volatile

34CONFIDENTIAL

VOLATILE PIGGY-BACKING PRECAUTIONS

• Volatile piggybacking is fragile! Use at your own risk!

• Ensures only visibility, thus applicable for “single writer /

multiple readers” scenarios only

• It does not ensure compound atomicity in case of multiple

writes/reads.

Image credit: http://www.noomii.com/blog/5949-warning-union-info-centre-scam

35CONFIDENTIAL

THREAD CONFINEMENT

• Thread confinement is a simple yet powerful technique used

to achieve thread safety without synchronization.

• The simple idea:

• If data is only accessed from a single thread,

no synchronization is needed.

• Examples:

• Swing – visual components are confined to the event

dispatch thread

• JDBC Connection Pools

36CONFIDENTIAL

CONFINEMENT MECHANISMS

• Java does not provide language-level

mechanisms that enforce thread

confinement.

• Must be enforced by the application

design and its implementation

• Java provides mechanisms that help maintaining confinement:

• Access modifiers

• Local variables

• ThreadLocal

Image credit: http://www.treatmentadvocacycenter.org/about-us/our-blog/69-no-state/2109-solitary-confinement-like-gasoline-on-fire

37CONFIDENTIAL

AD-HOC THREAD CONFINEMENT

• Developer is completely responsible to confine object to

thread. Language features (like local variables, access

modifiers) are not used

• State must be shared in a specific way:

• All shared data – marked as volatile

• Only a single thread must be able to write to the

shared data - requires developer’s carefulness and

discipline

• Not recommended approach (due to its fragility)

38CONFIDENTIAL

STACK CONFINEMENT

• Special case of thread

confinement

• An object can only be

reached through a

local variable

• The developer must

ensure that the object

reference does not

escape the method

• Ensures thread safety even if the confined object itself is not

thread-safe

39CONFIDENTIAL

STACK CONFINEMENT

• Example:

public static String format(Date date) {

DateFormat df = new SimpleDateFormat("yyyy-MM-dd");

return df.format(date);

}

• We only have one reference to the SimpleDateFormat object

• The reference is held in a local variable and therefore confined

to the executing thread

40CONFIDENTIAL

STACK CONFINEMENT

private static final DateFormat df =

new SimpleDateFormat("yyyy-MM-dd");

public static String format(Date date) {

return df.format(date);

}

41CONFIDENTIAL

STACK CONFINEMENT

private static final DateFormat df =

new SimpleDateFormat("yyyy-MM-dd");

public static String format(Date date) {

return df.format(date);

}

No longer

“stack confined”

42CONFIDENTIAL

THREAD CONFINEMENT WITH ThreadLocal

java.lang.ThreadLocal<T>:

• Provides thread-local variables

• Each thread has its own, independently initialized copy

of the variable (accessed via ThreadLocal’s get() or

set() methods)

• ThreadLocal instances are typically private static fields

in classes that wish to associate state with a thread

43CONFIDENTIAL

THREAD CONFINEMENT WITH ThreadLocal

Example: DateFormat is not thread-safe, so we use thread

confinement:

private static final ThreadLocal<DateFormat> tdf =

new ThreadLocal<DateFormat>() {

protected DateFormat initialValue() {

return new SimpleDateFormat("yyyy-MM-dd");

}

};

public String threadConfined(Date date) {

return tdf.get().format(date);

}

44CONFIDENTIAL

OBJECT ESCAPE

• An object is said to have escaped if it is published before

intended.

Image credit: http://www.humbersidefire.gov.uk/your-safety/safety-in-the-home/escape

45CONFIDENTIAL

OBJECT ESCAPE (EXAMPLE)

• Store a reference in a public static field, where any class and thread

could see it:

public static List<String> unsafeList;

public void initialize() {

unsafeList = new ArrayList<String>();

}

• Return a reference from a non-private method:

class UnsafeCurrencies {

private String[] currencies = new String[] {"USD",

"GBP", "BGN", "EUR", "AUD"};

public String[] getCurrencies() { return currencies; }

}

46CONFIDENTIAL

JAVA

OBJECT ESCAPE (EXAMPLE)

BYTECODE

…final com.threadconfinement.ThisEscape this$0;

…0: aload_01: aload_12: putfield #1// Field this$0:Lcom/threadconfinement/ThisEscape;5: aload_06: invokespecial #2// Method java/lang/Object."<init>":()V9: return…

public class ThisEscape {

public ThisEscape(EventSource source) {

source.registerListener(

new EventListener() {

public void onEvent(Event e) {

doSomething(e);

}

});

}

}

47CONFIDENTIAL

JAVA

OBJECT ESCAPE (EXAMPLE)

BYTECODE

…final com.threadconfinement.ThisEscape this$0;

…0: aload_01: aload_12: putfield #1// Field this$0:Lcom/threadconfinement/ThisEscape;5: aload_06: invokespecial #2// Method java/lang/Object."<init>":()V9: return…

public class ThisEscape {

public ThisEscape(EventSource source) {

source.registerListener(

new EventListener() {

public void onEvent(Event e) {

doSomething(e);

}

});

}

}

48CONFIDENTIAL

BENEFITS

• No accidental complexitySIMPLICITY2

1

• No lock contention

• Scales really well due to the lack of

synchronization overhead

PERFORMANCE

& SCALABILITY

3 • No race conditionsNO RISK OF

DEADLOCKS

49CONFIDENTIAL

THE END

top related