concurrency in jdk 5.0 cit concurrency · cit concurrency java implicit concurrency (3) •j dk 5.0...

Post on 03-Jun-2020

118 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

CIT

Con

curr

ency Concurrency in JDK 5.0

Thread-safe collections, Task Management, Synchronizers, Low-

level Facilities

CIT

Con

curr

ency

Java Implicit Concurrency (1)• AWT and Swing

– Background event thread– Event Listener classes must be thread-safe

• TimeTask – scheduling and periodic execution of tasks– TimerTask events execute in the Timer thread– TimerTasks must be thread safe

• Servlets and JavaServer Pages– Servlet containers create multiple threads and may call a

given servlet concurrently from multiple threads for multiple requests

– Servlets classes must be thread safe• RMI

– Remote classes must be thread safe

CIT

Con

curr

ency

Java Implicit Concurrency (2)• Thread safe class

– Must behave correctly in a single-threaded environment• No sequence of operations (public interface) puts objects in an

invalid state, • Or observe the object to be in an invalid state• Or violate any of the class’s invariants, pre- and post-

conditions

– Must continue to behave correctly when accessed from multiple threads

• Regardless of the scheduling or interleaving of the execution ofthose threads by the runtime environment

• Without any additional synchronisation on the part of the calling code

CIT

Con

curr

ency

Java Implicit Concurrency (3)• JDK 5.0

– java.util.concurrent– JVM-level changes (exploitation of hardware

level concurrency support – compare-and-swap instruction)

– Low-level utility classes – locks and atomic variables

– High-level utility classes – OS constructs (e.g. semaphores, mutexes, barriers), thread pools and thread-safe collection classes

CIT

Con

curr

ency

Thread-safe collections (1)• Collections

– Some are already thread safe: Hashtable and Vector– The rest can be made thread safe: syncrhonised wrapper

factories Collections.synchronisedList/Map/Set– Need to hold a lock while iterating!

• Fail-fast iterators• ConcurrentModificationException – conditional thread-safety

• java.util.concurrent– ConcurrentHashMap, CopyOnWriteArrayList,

CoppyOnWriteArraySet, Queue, BlockingQueue• Weakly consistent iterators

– A removed item not already returned will not be returned– An added item after the start of the iteration may or may not be

returned– No element will be returned twice in a single iteration

CIT

Con

curr

ency

Thread-safe collections (2)• CopyOnWriteArrayList/Set

– A new copy is created whenever an element is added or removed

– Avoids locking during iteration– Useful for list of listeners

• ConcurrentHashMap– Cannot be locked for exclusive use, but provides atomic

methods for common compound operations, e.g. put-if-absent

– Returns weakly consistent iterators• Queue interface – FIFO and priority classes• BlockingQueue – bounded or unbounded

– Producer/Consumer

CIT

Con

curr

ency

Bounded Buffer (1)• A bounded buffer consists of a fixed number of

slots– Items are put into the buffer by a producer process and

removed by a consumer process – It can be used to smooth out transfer rates between the

producer and consumer

CIT

Con

curr

ency

Bounded Buffer (2)public interface Buffer {…}

class BufferImpl implements Buffer {…

public synchronized void put(Object o) throws InterruptedException {

while (count==size) wait();buf[in] = o; ++count; in=(in+1)%size;notify();

}public synchronized Object get()

throws InterruptedException {while (count==0) wait();Object o =buf[out]; buf[out]=null; --count; out=(out+1)%size;notify();return (o);}

}

We separate the interface to permit an alternative implementation later.

CIT

Con

curr

ency

Bounded Buffer (3)class Producer implements Runnable {

Buffer buf;String alphabet= "abcdefghijklmnopqrstuvwxyz";

Producer(Buffer b) {buf = b;}

public void run() {try {

int ai = 0;while(true) {

ThreadPanel.rotate(12);buf.put(new Character(alphabet.charAt(ai)));ai=(ai+1) % alphabet.length();ThreadPanel.rotate(348);

}} catch (InterruptedException e){}

}}

Similarly Consumer which calls buf.get()

CIT

Con

curr

ency

Bounded Buffer (4)• The same in java 5.0

– The buffer

– The consumer

– The producer

LinkedBlockingQueue<Character> buf = new LinkedBlockingQueue<Character>(n);

buf.put(new Character(alphabet.charAt(ai)));

Character c = buf.take();

CIT

Con

curr

ency

Task Management (1)• Executor interface

– Objects that run Runnables– Separate task submission from task execution policy– Various threading options: background thread, thread

pool, in the calling thread (pass-through), new thread (thread-per-request), in another JVM

– Instantiation through factory methods• Executors.newCachedThreadPool()• Executors.newFixedThreadPool(int n)• Executors.newSingleThreadExecutor()

• ExecutorService interface– Extension of executor with lifecycle management of

execution service

CIT

Con

curr

ency

Task Management (2)class ReliableWebServer {

Executor pool = Executors.newFixedThreadPool(7);public static void main(String[] args) {

ServerSocket socket = new ServerSocket(80);while (true) {

final Socket connection = socket.accept();Runnable r = new Runnable() {

public void run() {handleRequest(connection);

}};pool.execute(r);

}}

}

CIT

Con

curr

ency

Task Management (3)• Executor customisation through custom

ThreadFactory• In case of execution inability –

RejectedExecutionHandler– Throw exception– Discard task– Execute in caller’s thread– Discard old task in queue

• Custom executors with overidden beforeExecuteand afterExecute– Instrumentation, logging, timing, reinitialisation of

thread-local variables, execution customisations

CIT

Con

curr

ency

Task Management (4)• Callable: result bearing Runnable• Future interface

– FutureTask – implements interface, can be submitted to an Executor

• ExecutorService.submit() – returns a Future interface

– Future.get() – retrieves results or throws ExecutionException – it is blocking

• CompletionService interface– Decouple results processing from task

execution, e.g. producer/consumer– ExecutorCompletionInterface

CIT

Con

curr

ency

Task Management (5)public class Cache<K, V> {

ConcurrentMap<K, FutureTask<V>> map = new ConcurrentHashMap();

Executor executor = Executors.newFixedThreadPool(8);public V get(final K key) {

FutureTask<V> f = map.get(key);if (f == null) {

Callable<V> c = new Callable<V>() {public V call() {

// return value associated with key}

};f = new FutureTask<V>(c);FutureTask old = map.putIfAbsent(key, f);if (old == null) executor.execute(f);else f = old;

}return f.get();

}}

CIT

Con

curr

ency

Semaphores (1)• Semaphore s is an

integer variable that can take only non-negative values– Semaphores are widely

used for dealing with inter-process synchronization in operating systems

• The only operations permitted on s are up(s) and down(s)– Blocked processes are

held in a FIFO queue.

down(s): if s >0 thendecrement s

elseblock execution of the calling process

up(s): if processes blocked on s thenawaken one of them

elseincrement s

CIT

Con

curr

ency

Semaphores (2)

public class Semaphore {

private int value;

public Semaphore (int initial) { value = initial;}

synchronized public void up() {++value;notify();

}

synchronized public void down()throws InterruptedException {

while (value==0) wait();--value;

}}

CIT

Con

curr

ency

Bounded Buffer (2)public interface Buffer {…}

class BufferImpl implements Buffer {…

public synchronized void put(Object o) throws InterruptedException {

while (count==size) wait();buf[in] = o; ++count; in=(in+1)%size;notify();

}public synchronized Object get()

throws InterruptedException {while (count==0) wait();Object o =buf[out]; buf[out]=null; --count; out=(out+1)%size;notify();return (o);}

}

We separate the interface to permit an alternative implementation later.

CIT

Con

curr

ency

Nested Monitors (1)• Suppose that, in place of using the count variable

and condition synchronization directly, we instead use two semaphores full and empty to reflect the state of the buffer. class SemaBuffer implements Buffer {

Semaphore full; //counts number of itemsSemaphore empty; //counts number of spaces

SemaBuffer(int size) {this.size = size; buf = new Object[size];full = new Semaphore(0);empty= new Semaphore(size);

}…}

CIT

Con

curr

ency

Nested Monitors (2)

• Empty is decremented during a put operation, which is blocked if empty is zero

• Full is decremented by a get operation, which is blocked if full is zero.

synchronized public void put(Object o) throws InterruptedException {

empty.down();buf[in] = o;++count; in=(in+1)%size;full.up();

}synchronized public Object get()

throws InterruptedException{full.down();Object o =buf[out]; buf[out]=null;--count; out=(out+1)%size;empty.up();return (o);

}

Does this behave as desired?

CIT

Con

curr

ency

Nested Monitors (3)• The only way to avoid nested monitor deadlock in

Java is by careful design– In this example, the deadlock can be removed by

ensuring that the monitor lock for the buffer is not acquired until after semaphores are decremented.

public void put(Object o) throws InterruptedException {

empty.down();synchronized(this){buf[in] = o; ++count; in=(in+1)%size;

}full.up();

}

CIT

Con

curr

ency

Syncrhonizer Classes• Coordination and control of execution flow of threads• Semaphore

– Thread acquire any number of permits– Mutex – mutual exclusion semaphore or binary semaphore

• Similar to locks but allow release from different thread – useful in deadlock recovery

• CyclicBarrier– Reusable barrier for a group of threads– Maybe used with a timeout

• CountdownLatch– Similar to barrier but not reusable– Separates barrier arrival from waiting– Can be used as a starting gate

• Exchanger– Rendezvous– Similar to a barrier of two but with data exchange

CIT

Con

curr

ency

Readers/Writers (1)• A shared database is accessed by two kinds of

processes. Readers execute transactions that examine the database while Writers both examine and update the database. A Writer must have exclusive access to the database; any number of Readers may concurrently access it.

Light blue indicates database access.

CIT

Con

curr

ency

Readers/Writers (2)• We concentrate on the monitor implementation• We define an interface that identifies the monitor

methods that must be implemented, and develop a number of alternative implementations of this interface. – Firstly, the safe READWRITELOCK.

interface ReadWrite {public void acquireRead()

throws InterruptedException;public void releaseRead();public void acquireWrite()

throws InterruptedException;public void releaseWrite();

}

CIT

Con

curr

ency

Readers/Writers (3)class ReadWriteSafe implements ReadWrite {

private int readers =0;private boolean writing = false;

public synchronized void acquireRead()throws InterruptedException {

while (writing) wait();++readers;

}

public synchronized void releaseRead() {--readers;if(readers==0) notify();

}

Unblock a single writer when no more readers.

CIT

Con

curr

ency

Readers/Writers (4)public synchronized void acquireWrite()

throws InterruptedException {while (readers>0 || writing) wait();writing = true;

}

public synchronized void releaseWrite() {writing = false;notifyAll();

}}

Unblock all readers

This monitor implementation suffers from the WRITE progress problem: possible writer starvation if the number of readersnever drops to zero.

Strategy: Block readers if there is a writer waiting.

CIT

Con

curr

ency

Readers/Writers (5)class ReadWritePriority implements ReadWrite{

private int readers =0;private boolean writing = false;private int waitingW = 0; // no of waiting Writers.public synchronized void acquireRead()

throws InterruptedException { while (writing || waitingW>0) wait();

++readers; }public synchronized void releaseRead() { --readers; if (readers==0) notify(); }synchronized public void acquireWrite() { ++waitingW;

while (readers>0 || writing) try{ wait();} catch(InterruptedException e){}

--waitingW; writing = true; }synchronized public void releaseWrite() { writing = false; notifyAll(); }

}

Both READand WRITEprogress properties can be satisfied by introducing a turnvariable as in the Single Lane Bridge.

CIT

Con

curr

ency

Low-Level facilities• Locks

– Lock interface– Like the syncrhonized lock but with variations

• Timed waits, interruptible waits, lock polling, multiple condition wait sets per lock, non-blocking structured locking

– Reentrant lock implements interface• More scalable than synchronised• But, requires explicit unlocking

– Condition interface • Generalisation of wait()/notify() • Multiple conditions on the same lock

– ReadWriteLock– Can be fair, but fairness doesn’t scale

• Atomic variables– AtomicInteger/Long/Boolean/etc.

top related