1 Transition from Blocked to Runnable Entering the Blocked state A - - PowerPoint PPT Presentation

1
SMART_READER_LITE
LIVE PREVIEW

1 Transition from Blocked to Runnable Entering the Blocked state A - - PowerPoint PPT Presentation

Thread states 1. New: created with the new operator (not yet started ) 2. Runnable: either running or ready to run 3. Blocked: Java threads: synchronization deactivated to wait for something 4. Dead: has executed its run


slide-1
SLIDE 1

1

1

Java threads: synchronization

2

Thread states

  • 1. New:
  • created with the new operator (not yet started)
  • 2. Runnable:
  • either running or ready to run
  • 3. Blocked:
  • deactivated to wait for something
  • 4. Dead:
  • has executed its run method to completion, or

terminated by an uncaught exception

  • a started thread is executed in its own run-time

context consisting of: program counter, call stack, and some working memory (registers, cache)

3

Thread states

4

Thread states (cont.)

  • don't confuse the interface java.lang.Runnable with

the state Runnable

  • "running" is not a separate state within Runnable, but

Thread.currentThread () // static method identifies the current thread object (for itself)

  • thread.isAlive () tells if the thread has been started (is

not New) and not yet Dead – you cannot directly ask whether an alive thread is Runnable or Blocked – you cannot directly ask whether a non-alive thread is still New or already Dead

slide-2
SLIDE 2

2

5

Entering the Blocked state

A thread enters the blocked state when:

  • 1. the thread goes to sleep by calling the sleep method
  • 2. the thread calls an operation that blocks until IO
  • perations are complete
  • 3. the thread tries to acquire a lock that is currently

held by another thread (mutual exclusion)

  • 4. the thread waits for a condition

6

Transition from Blocked to Runnable

A blocked thread moves into the Runnable state when

  • 1. if in sleep, the specified number of milliseconds

have been expired

  • 2. if waiting for the completion of an IO operation, the

IO operation have finished

  • 3. if waiting for a lock that was owned by another

thread, the other thread have released its ownership

  • f the lock
  • 4. if waits for a condition, another thread signals that

the condition (may) have changed – additionally, can wait for a lock or a condition with a timeout

7

Java Memory Model

  • computers can temporarily hold memory values in

registers or local memory caches, and the compiler can reorder instructions to optimize throughput – without synchronization, threads (interleaved or parallel) may see out-of-date and/or out-of-order values for the same memory locations

  • locks always ensure that all calculated results are

visible to other threads (flushing of caches, etc.)

  • alternatively, you can declare a flag field as volatile:

private volatile boolean done; . . public boolean isDone () { return done; }

  • a write to a volatile variable synchronizes with all

subsequent reads of that same variable (all reads and writes are atomic, even for long and double)

8

Mutual exclusion from critical code

  • basic way to protecting a shared code block:

myLock.lock (); // a ReentrantLock object try { critical section } finally { myLock.unlock (); }

  • only one thread at a time can enter the critical section

(identified and protected by this particular lock)

  • any other threads calling on this lock, are blocked

until the first thread unlocks

  • the finally clause makes sure the lock is unlocked

even if an exception is thrown

slide-3
SLIDE 3

3

9

Fairness

  • you can specify that you want a fair locking policy:

Lock fairLock = new ReentrantLock (true);

  • a fair lock favors the thread that has been waiting

for the longest time

  • by default, locks are not required to be fair

– for implementation reasons fair locks can be much slower than regular locks – anyway, you have no guarantee that the thread scheduler provided by the plarform is fair

  • so if the thread scheduler neglects a thread,

it may not get the chance to be treated fairly by the lock

10

Condition objects

  • a lock protects sections of code, allowing only one

thread to execute the code at a time – a lock manages threads that are trying to enter a protected code segment

  • a lock can have one or more associated condition
  • bjects

– each condition object manages threads that have entered a protected code section but that cannot proceed for some reason (usually, lack of data / resource)

11

Condition objects (cont.)

  • use a condition object to manage threads that have

acquired a lock but cannot proceed with useful work Condition cond = lock.newCondition (); . . lock.lock (); try { while (!(ok to proceed)) // try until succeeds cond.await (); // data available: do something useful } finally { lock.unlock (); }

  • must itself check that the condition is (still) valid

12

Condition objects (cont.)

  • some other thread must call the signalAll method to

wake up any waiting threads change some item used in condition test . . cond.signalAll (); // or rarely: signal ()

  • the condition wait must always be done in a loop

while (! condition) cond.await ();

  • multiple threads may compete to acquire the lock
  • the first one can use up resources, and so others

must then enter back to the blocked state to wait

  • additionally, a "spurious wakeup" (without signal) is

permitted to occur (depending on the OS)

slide-4
SLIDE 4

4

13

Keyword "synchronized"

  • since version 1.0, every object has an implicit lock to

be used in so-called monitor methods: public synchronized void method () { body } this is the equivalent of the following pseudocode: public void method () { // use explicit lock this.implicitLock.lock (); // pseudocode try { body } finally { this.implicitLock.unlock(); } }

14

Keyword synchronized (cont.)

  • the monitor lock also has a single implicit associated

condition with the following operations – wait adds a thread to its set of waiting threads – notifyAll unblocks all waiting threads to compete for access

  • these correspond to the following lock calls

– implicitCondition.await (); // pseudocode – implicitCondition.signalAll ();

  • the wait and notifyAll methods are final methods in

Object – so the Condition methods had to be renamed differently: await and signalAll

15

Synchronized code blocks

  • an implicit lock can be acquired also by entering a

code block synchronized by an object lock: synchronized (obj) { // any object critical section // implicit lock and unlock }

  • the lock is reentrant: if a thread has acquired the

lock, it can acquire it again (increments a count)

  • similarly, a monitor method can call other monitor

methods with the same implicit lock without waiting

  • you can declare a static monitor method: it uses the

the associated class object ("X.class") as its lock

16

Limitations of implicit locks and conditions

  • you cannot interrupt a thread that is waiting to

acquire a lock

  • you cannot specify a timeout when trying to acquire

a lock

  • having only one single condition per lock can be

inefficient – cannot separate buffer empty (cannot take) vs. buffer full (cannot put) conditions

  • the virtual machine locking primitives do not map

well to the most efficient locking mechanisms available in modern hardware

slide-5
SLIDE 5

5

17

Lock testing and timeouts

  • can be cautious about acquiring a lock:

if (myLock.tryLock ()) { // now the thread owns the lock try { do something } finally { myLock.unlock (); } } else { do something else }

  • can call tryLock with a timeout parameter:

if (myLock.tryLock(10,TimeUnit.MILLISECONDS)) . . . – TimeUnit can be: SECONDS, MILLISECONDS, MICROSECONDS, or NANOSECONDS.

18

Lock testing and timeouts (cont.)

  • if you call tryLock with a timeout, then it can throw

InterruptedException when interrupted – can try to break up deadlocks and such – the lockInterruptibly method has the same meaning as tryLock with an infinite timeout

  • can also supply a timeout for a condition wait;

myCondition.await (10, TimeUnit.MILLISECONDS)); – returns if another thread has called signalAll - or if the given timeout has elapsed – await methods throw an InterruptedException if the thread is interrupted (but awaitUninterruptibly)

19

Summary of synchronization operations

  • synchronized (lock) { . . use shared data }
  • synchronized void method () { . . use shared data }
  • lock.lock () { . . } finally { lock.unlock (); } // explicit
  • waiting for a condition to proceed:

try { . . while (!(cannot proceed)) wait (); . . // means: this.wait (); } catch (InterruptedException e) { . .

  • either anyObject.wait ();
  • r condition.await ();
  • either anyObject.notifyAll (); or condition.signalAll ();

20

Recommendations

  • 1. it is best to use neither lock/condition nor the old

monitor methods/code blocks ("synchronized")

  • in many situations, better to use mechanisms of

the java.util.concurrent package that do all the locking and synchronization for you

  • for example, a blocking queue can synchronize

threads that work on a common pipeline

  • 2. if the monitor methods work for your situation,

prefer using them:

  • less code to write and so less room for error
  • 3. use explicit locks/conditions only if you need the

additional power of these constructs

slide-6
SLIDE 6

6

21

java.util.concurrent: thread management tools

  • ReentrantReadWriteLock provides shared access for readers,

and exclusive access for a writer

  • BlockingQueue <E> can cause a thread to block when trying to

add to a full queue or trying to remove from empty one – ConcurrentLinkedQueue <E> and ArrayBlockingQueue <E> provide optionally-bounded/bounded thread-safe queues

  • interface ConcurrentMap <K,V> implemented efficiently by

– ConcurrentHashMap and ConcurrentSkipListMap

  • CopyOnWriteArrayList <E> and CopyOnWriteArraySet <E>

provide thread-safe collections (reads outnumber mutations)

  • Callable <T> plus Future <T> can return and hold the result of

an asynchronous computation (can test, time-out, and cancel)

  • you can give a Runnable to a thread pool, and one of its idle

threads executes it; afterwards, that thread can serve again

  • synchronizers: CyclicBarrier, CountDownLatch, Exchanger,

SynchronousQueue, and Semaphore

  • AtomicInteger, AtomicLong, AtomicReference, etc.: lock-free

thread-safe programming on single variables

22

Atomic variables

  • support lock-free thread-safe programming on single

variables (objects) – extends the notion of volatile: provide atomic and synchronized access to single values (visibility!)

  • enable implementations to use efficient atomic

machine instructions that available on processors (but no guarantees: might entail internal locking ..) AtomicLong seqNo = new AtomicLong (0); . . long next () { return seqNo.getAndAdd(1); } // atomic – may not work when state involves invariants..

  • atomic variables do not replace Integer, Long, etc.

– do not provide hashCode or compareTo (since expected to change, no good as Map keys)

23

A producer-consumer solution

class IntProducer implements Runnable { private BlockingQueue <Integer> queue; public IntProducer (BlockingQueue <Integer> q) { queue = q; new Thread (this).start (); } public void run () { try { // "put" may block for (int x = 0; x < 100; x++) { Thread.sleep (delay); . . queue.put (x); } } catch (InterruptedException e) { } } }

24

A producer-consumer solution (cont.)

class IntConsumer implements Runnable { private BlockingQueue <Integer> queue; public IntConsumer (BlockingQueue <Integer> q) { queue = q; new Thread (this).start (); } public void run () { try { // "take" may block while (true) { int value = queue.take (); . . } } catch (InterruptedException ex) { } } } . . BlockingQueue <Integer> q = new ArrayBlockingQueue <Integer> (10); // capacity