java- concurrent programming - synchronization (part 2)

21
CONCURRENT PROGRAMMING SYNCHRONIZATION (PART 2) PROGRAMMAZIONE CONCORRENTE E DISTR. Università degli Studi di Padova Dipartimento di Matematica Corso di Laurea in Informatica, A.A. 2015 – 2016 [email protected]

Upload: riccardo-cardin

Post on 09-Feb-2017

861 views

Category:

Software


1 download

TRANSCRIPT

Page 1: Java- Concurrent programming - Synchronization (part 2)

CONCURRENT PROGRAMMINGSYNCHRONIZATION (PART 2)PROGRAMMAZIONE CONCORRENTE E DISTR.Università degli Studi di Padova

Dipartimento di Matematica

Corso di Laurea in Informatica, A.A. 2015 – [email protected]

Page 2: Java- Concurrent programming - Synchronization (part 2)

2Programmazione concorrente e distribuita

SUMMARY Conditions Volatile variables Atomics Thread confinement Immutability

Riccardo Cardin

Page 3: Java- Concurrent programming - Synchronization (part 2)

3Programmazione concorrente e distribuita

CONDITIONS Condition variables

Often a thread enters a critical section only to discover that it can’t proceedA condition is not fulfilled

We can try to use a lock

Riccardo Cardin

if (bank.getBalance(from) >= amount) { // Thread might be deactivated at this point bank.transfer(from, to, amount);}

public void transfer(int from, int to, int amount) { bankLock.lock(); try { while (accounts[from] < amount) { // wait } // transfer funds }

No thread can withdraw money,

due to the acquired lock: DEADLOCK!!

Page 4: Java- Concurrent programming - Synchronization (part 2)

4Programmazione concorrente e distribuita

CONDITIONS To avoid unpleasant deadlock, use conditions

A condition variable is built from a lock

A thread owning the lock, calls await on the condition

The lock is released by the thread Thread is not made runnable when the lock i available. It stays

deactivated until the condition will be fulfilled Wait set for the condition

Riccardo Cardin

class Bank { private Condition sufficientFunds; public Bank() { // Getting a condition with an evocative name sufficientFunds = bankLock.newCondition(); }}

sufficientFunds.await();

Page 5: Java- Concurrent programming - Synchronization (part 2)

5Programmazione concorrente e distribuita

CONDITIONS When another thread fulfills the condition, it

should notify other awaiting threads

One of the awaiting thread will be eligible to acquire the lock and to continue where it left off Lock must be available

The condition may be fulfilled Retry to check that condition are met over and over again

An awaiting thread cannot reactive itself: be carefull!

Riccardo Cardin

sufficientFunds.signalAll();

while (!(/* ok to proceed */)) { condition.await();}

Page 6: Java- Concurrent programming - Synchronization (part 2)

6Programmazione concorrente e distribuita

CONDITIONS It’s important that some thread calls the signalAll method eventually If no other thread bother to reactivate a waiting thread,

it will neve run again DEADLOCK!

Call signalAll whenever the state of an object changes

Riccardo Cardin

public void transfer(int from, int to, int amount) { bankLock.lock(); try { while (accounts[from] < amount) sufficientFunds.await(); // transfer funds sufficientFunds.signalAll(); } finally { bankLock.unlock(); } }

Page 7: Java- Concurrent programming - Synchronization (part 2)

7Programmazione concorrente e distribuita

CONDITIONS

Riccardo Cardin

Page 8: Java- Concurrent programming - Synchronization (part 2)

8Programmazione concorrente e distribuita

CONDITIONS Intrinsic locks have a single associated condition

The wait method adds a thread to the wait setThe notifyAll method unblocks waiting threads

Having a single condition per intrinsic lock can be inefficient Which condition has been safisfied? All threads waiting have

to be resumedRiccardo Cardin

public synchronized void transfer(int from, int to, int amount) throws InterruptedException { while (accounts[from] < amount) wait(); // wait on intrinsic object lock // transfer funds notifyAll(); // notify all threads waiting}

Page 9: Java- Concurrent programming - Synchronization (part 2)

9Programmazione concorrente e distribuita

CONDITIONS PITFALLS What should you use in your code, Locks or synchronized methodsNeither. In many situation it can be used one of the

mechanisms of the java.util.concurrent package i.e. – Blocking queues

If you have to choose, use synchronized blocksUse Lock / Condition if you really need the

additional power that gives to you You have to define a custom protocol of synchronization

Riccardo Cardin

Do not underestimate the powers of the dark side of concurrency-- Riccardo Cardin

Page 10: Java- Concurrent programming - Synchronization (part 2)

10Programmazione concorrente e distribuita

VOLATILE VARIABLES

Cached values and operations reodering are evil! A volatile variable is not cached by threads

Share the visibility feature of synchronized Threads will automatically see the most up-to-date value

...but non of the atomicity features Possible race-conditions on multiple operations

Riccardo Cardin

If you write a variable which may next be read by another thread, or you read a variable which may have last been written by another thread, you must use synchronization.

-- Brian Goetz

private volatile boolean done;public boolean isDone() { return done; }public void setDone() { done = true; }

Page 11: Java- Concurrent programming - Synchronization (part 2)

11Programmazione concorrente e distribuita

VOLATILE VARIABLES When to use volatile vars instead of locks

Writes do not depend on its current value

DO NOT use for implementing counters!The variable does not partecipate in invariants with

other variablesSlightly better performances

Riccardo Cardin

// Not atomic, you need synchronizationpublic void flipDone() { done = !done; }

volatile boolean shutdownRequested;public void shutdown() { shutdownRequested = true; }public void doWork() { while (!shutdownRequested) { // do stuff }}

Pattern of use: status

flag

Page 12: Java- Concurrent programming - Synchronization (part 2)

12Programmazione concorrente e distribuita

VOLATILE VARIABLES

Riccardo Cardin

Page 13: Java- Concurrent programming - Synchronization (part 2)

13Programmazione concorrente e distribuita

ATOMICS There are operations other than setter and

getter provided by volatile variables java.util.concurrent.atomic provides classes

that guarantee atomicity of other operations AtomicInteger, AtomicBoolean, AtomicLong, ...

Riccardo Cardin

class AtomicCounter { private AtomicInteger c = new AtomicInteger(0); public void increment() { c.incrementAndGet(); } public void decrement() { c.decrementAndGet(); } public int value() { return c.get(); }}

Uses low level CPU operations, that don’t need synchronization

(CAS, compare-and-swap)

Page 14: Java- Concurrent programming - Synchronization (part 2)

14Programmazione concorrente e distribuita

THREAD CONFINEMENT The best solution to concurrency problems is to

not share any mutable stateUse ThreadLocal helper class to give each thread an

instance of a class

When thread terminates, value is garbage collected Do not use as a replacement for global variables

Many JDK classes are not thread-safe SimpleDateFormat, Random, ...

Riccardo Cardin

public static final ThreadLocal<SimpleDateFormat> dateFormat = new ThreadLocal<SimpleDateFormat>() { protected SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd"); }};String dateStamp = dateFormat.get().format(new Date());

Page 15: Java- Concurrent programming - Synchronization (part 2)

15Programmazione concorrente e distribuita

IMMUTABILITY

All the problems described so far have to do with accessing shared mutable state If object state cannot be modified, the risks go away Immutable object are simple

There are not different states for complex objects Immutable object are safer

No untrusted code can modify directly object’s state or retain a reference to modify it later

Java does not formally defined immutability It is not sufficient declaring all fields as final

Riccardo Cardin

Immutable objects are always thread-safe-- Brian Goetz

Page 16: Java- Concurrent programming - Synchronization (part 2)

16Programmazione concorrente e distribuita

IMMUTABILITY An object is immutable if:

Its state cannot be modified after construction So a immutable class has reference only to (effectively)

immutable classesAll its fields are final It is properly constructed

The this reference does not escape during construction, i.e. calling code outside the class, and passing this

Can use mutable state for internal representation Are this kind of object useful?

There is a big difference between an object been immutbale and the reference to it being immutable

Riccardo Cardin

Page 17: Java- Concurrent programming - Synchronization (part 2)

17Programmazione concorrente e distribuita

IMMUTABILITY

Riccardo Cardin

Page 18: Java- Concurrent programming - Synchronization (part 2)

18Programmazione concorrente e distribuita

IMMUTABILITY

The final keyword on fields makes possibile the guarantee on initialization safetyA more limited version of the const in C++No reorder will be done by the compilerSo, final fields can be accessed without additional

synchronizationBetter maintainability

It’s time to have a look to an immutable class!Riccardo Cardin

Immutable objects can be used safely by any thread without additional synchronization.

-- Brian Goetz

Page 19: Java- Concurrent programming - Synchronization (part 2)

19Programmazione concorrente e distribuita

IMMUTABILITY

Riccardo Cardin

class OneValueCache { private final BigInteger lastNumber;    private final BigInteger[] lastFactors; // Do not use directly a mutable object to construct // an immutable object    public OneValueCache(BigInteger i, BigInteger[] factors) { lastNumber = i;        lastFactors = Arrays.copyOf(factors, factors.length);    }

// Do not late ‘escape’ an internal value of the immutable // object. In this way no other code can maliciously modify // that state public BigInteger[] getFactors(BigInteger i) { if (lastNumber == null || !lastNumber.equals(i))         return null;        else         return Arrays.copyOf(lastFactors, lastFactors.length);       } }}

Page 20: Java- Concurrent programming - Synchronization (part 2)

20Programmazione concorrente e distribuita

EXAMPLES

Riccardo Cardin

https://github.com/rcardin/pcd-snippets

Page 21: Java- Concurrent programming - Synchronization (part 2)

21Programmazione concorrente e distribuita

REFERENCES Chap. 14 «Multithreading», Core Java Volume I - Fundamentals, Cay

Horstmann, Gary Cornell, 2012, Prentice Hall Chap. 3 «Sharing Objects», Java Concurrency in Practice, Brian

Goetz, 2006, Addison-Wesley Professional Atomic Access https://

docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html Java theory and practice: Managing volatility

http://www.ibm.com/developerworks/library/j-jtp06197/ Java theory and practice: Going atomic

http://www.ibm.com/developerworks/library/j-jtp11234/ What is the difference of Atomic / Volatile / synchronize? http://

stackoverflow.com/questions/9749746/what-is-the-difference-of-atomic-volatile-synchronize

Riccardo Cardin