codes counter with print counter with yield counter with timeout counter with problem counter with...
Post on 21-Jan-2016
266 Views
Preview:
TRANSCRIPT
Codes
• counter with print• counter with yield• counter with timeout• counter with problem• counter with yield at bad place• counter with sync• counter with semaphore
Distributed Systems3. Java Threads
Simon Razniewski
Faculty of Computer ScienceFree University of Bozen-Bolzano
A.Y. 2014/2015
Why processes and threads
• Several processes– Skype– Browser– Music player
• Several actions within a process– send and receive at the same time– reaction to user input while doing expensive steps
(e.g. network communications, calculations, disk fetching)
Process
•What is a process?• The unit of computation inside an Operating System• A running program with its data and resources– Code (text) of the program– Data: global variables– Program Counter– CPU registers– Stack: parameters, local variables– Resources: open files, network connections, I/O, …
• JVM runs as a single process
Process
•What is a process?• The unit of computation inside an Operating System• A running program with its data and resources– Code (text) of the program– Data: global variables– Program Counter– CPU registers– Stack: parameters, local variables– Resources: open files, network connections, I/O, …
• JVM runs as a single process
Process States
init
ready running
blocked
terminated
creation
event wait for event
assign CPU
revoke CPU
termination
Active process
• Multitasking system multiple running processes• Single processor one active process
– Time sharing, context switch
Thread
• Lightweight process: smallest unit of computation that can be scheduled in an O.S.
• Shares code and data with other associated threads– Task: set of threads that refer to the same code and data– Process = task with (at least) a single thread!
• Task taken as synonym of process
• It is a single control-flow within a process• Multithreading like Multitasking• Execution of Java program: JVM creates a thread that
executes the main method– Other threads can be dynamically created
Thread: Features
• Memory sharing: threads share variables– No reserved memory for data and heap: all
threads in a process share the same address space• Private stack and program counter• Low context switch cost– No need to handle code&data– Much more performing than for processes
• But… privacy/synchronization issues: threads of the same task can modify each other’s data
Single vs Multithreaded Processes
Java Thread: Big PictureProcess
Code
Static variables
Memory
Thread 1Stack 1
local var., methods
PC 1
Thread 2Stack 2
local var., methods
PC 2
Thread 3Stack 3
local var., methods
PC 3
Implementation
• java.lang.Thread class• Provides the functionalities for a thread• With new(), the thread is created but is still
not active• start() activates the thread• start() calls run(), empty method– Extend Thread and override run() in order to
implement a thread!
Simple Skeletonclass SimpleThread extends Thread {
public void SimpleThread() { <constructor> }
public void run() { <behavior of each instance of SimpleThread>
}}
public class SimpleMain{
public static void main (string[] args){
Thread t1=new SimpleThread();t1.start(); //Thread t1 activated … don’t call run()
directly!… //HOW MANY THREADS HERE?
}}
A Thread not Thread
• Is it possible to define a JAVA thread that does not extend Thread?– JAVA does not support multiple inheritance
• Interface Runnable: a class denoting instances that can be run by a thread
• How-to– Implement Runnable and its run() method– Create a new object of this class– Create a new Thread passing the object as parameter of the
constructor– start() thread
Simple Skeletonclass SimpleRunnable extends MyClass
implements Runnable {
public void run() {<behavior here…>
}}
public class AnotherSimpleMain {public static void main(String args[]){
SimpleRunnable r = new SimpleRunnable();Thread t = new Thread(r);t.start();
}}
Thread Lifecycle
• New Thread– Thread created with new– Still inactive
• Runnable = executable (could be in execution)• Not runnable
– Cannot be currently scheduled for the execution• Dead
– Thread has autonomously finished its execution (end of run())– stop() method invoked on it
Not Runnable – Why?
• Waiting for I/O operation to terminate• Trying to access to synchronized
object/monitor queued• One of these methods has been invoked on it– sleep()– wait()– suspend()• Deprecated because prone to deadlock
• We will discuss these cases in detail…
Stopping a Thread
• Idea: stop the execution of a thread• stop() is deprecated because unsafe– We will see the notion of (un)locking– Basically, stop() causes the thread to
immediately release all resources (unexpectedly)– Objects protected by the lock could be in an
inconsistent state, and now accessed by other threads
• In general, google “Java Thread Primitive Deprecation”
How to Stop a Thread
• Using a recurring pattern (we will re-use it later on)
private Thread myself;
public void stop() { //user-defined! myself = null; }
public void run() { Thread thisThread = Thread.currentThread(); while (myself == thisThread) {
<behavior here…> //RECHECK CONDITION IF THE CODE IS LARGE
} }
A Shared Counter
• ParallelCounter– increment() increments the counter– decrement() decrements the counter
• CountingThread– Parameters:• String name• Int times
– Execution: increments or decrements the counter for times times
What Happens?
Incrementor i1 = new Incrementor("A",5000000);Incrementor i2 = new Incrementor("B",5000000);i1.start();i2.start();while (!i1.hasFinished || !i2.hasFinished) {}System.out.println(counter);
What is the final value of the counter (when both i1 and i2 have finished)?
Counter
static void increment() {counter++;
}
cur countercounter cur + 1
Byte code
Counter
static void increment() {counter++;
}
cur countercounter cur + 1
Byte code
What if we have a context switch here?
Remember: value is shared, cur is local
Counter
static void increment() {int curVal = counter;Thread.yield();counter = curVal+1;
}
=> Eclipse
The Problem
• Threads share the same address space• Common resources: objects can be manipulated by
multiple threads at the same time• Interference we need synchronization• Access control mechanisms: to define who and when
can correctly access to a resource– No deadlock: situation in which every thread is stuck– No livelock: situation in which threads continuously
execute without terminating– No starvation: we must guarantee that all threads can have
the possibility of accessing the resource sooner or later
Mutual Exclusion
• Operations on a shared objects by different threads cannot overlap in time
• No ordering constraint• Critical section: instructions that deal with the
object change• Critical sections of the same class cannot
overlap• At most one critical section of a class can be
executed at a given time
Solutions
• Ad-hoc algorithms with turn/busy variables– Difficult to generalize– Waiting for a resource reduces to an active cycle
(busy waiting)• Waste of resources
– Starvation?
Semaphores (Dijkstra)
• Non-negative integers indicating number of parallel accesses allowed
• manipulated through atomic operations: signal (V) incrementwait (P) decrement
• Read semaphore: when value=0, wait causes the thread to wait until the value becomes positive– Passive wait inside a queue– FCFS strategy to avoid starvation
• Binary semaphores: mutex
Mutual Exclusion with Semaphores
Thread 1
…s.wait();<critical section>s.signal();…
Thread 2
…s.wait();<critical section>s.signal();…
Semaphore s = new Semaphore(1);
N.B.: THIS IS NOT JAVA CODE
• This kind of semaphore is a lock
Limits of Semaphores
• Low-level programming construct• Easy to introduce errors: deadlock/livelock– Debugging concurrent programs is extremely
difficult• Examples in the mutex case– Inverting wait and signal makes it possible to
multiple access to the critical section– Using wait twice causes a deadlock
Monitor for Objects (Hoare)
Monitor (Abstract Model)
• Protects the data of a shared structure/resource– Data (state of the monitor) are persistent and
cannot be accessed directly• Object’s data attributes
– Public/Entry methods: unique entry point that can modify the state
Monitor Protection Levels• Level 1: mutual exclusion– Public methods are always mutually exclusive: at most one
thread can be active inside the monitor (lock)– If another thread tries to access one of the public methods
waits into an entry queue– Automatically enforced at the language level
• Level 2: regulates the order in which threads can access the resource– When an entry operation is called, it first checks a
synchronization condition (that induces an ordering)– Condition not met thread waits, monitor is freed – Suspension managed by the programmer through a condition
variable
Condition
• Special variable typecondition cond;
• Represents a queue containing waiting threads
• Monitor’s operations manipulate conditions through two operations– wait(cond) – signal(cond)
Signal and Wait
• Effect of wait(cond) – Thread is suspended and inserted into cond’s
queue– Monitor is freed– The thread will restart the execution after wait(cond), guaranteeing mutual exclusion
• Effect of signal(cond) – Reactivates one thread waiting in cond’s queue– Has no effect if cond’s queue is empty
Monitor QueuesMonitor
Entry queue
. . .
Condition queue (C1)
Condition queue (C2)
Condition queue (Cn)
active thread
Signal Semantics
• Execution of signal operation– Signaling thread Q (executes signal(cond))– Signaled thread P (extracted from cond’s queue)
• Both Q and P could execute… who has priority?– Signal and wait: Q halts and P continues• Blocking condition variables (Hoare’s monitor)
– Signal and continue: Q continues, P is notified and waits• Nonblocking condition variables (Mesa style monitor)
Signal Semantics: Schema
monitorfree?
entry queue
condition queue
in execution
Call
NO
YES
cond.wait()
monitor free
cond.signal_and_wait()
cond.signal_and_continue()
cond.signal_and_wait()
cond.signal_and_continue()
Signal and Wait
• Signaling thread: Q, signaled thread: P• Q is inserted into the entry queue– Or a second signal queue with higher
priority than the entry queue
• P is activated and occupies the monitor– No other process can
change the condition– Hence P can continue the
execution of the method– P restarts after thecond.wait()instructionthat blocked it
Signal and Continue (Java)
• Signaling thread: Q, signaled thread: P• Q continues (monitor still locked)• P is moved from cond’s queue
to the entry queue– Other processes can enter the
monitor between Q and PFirst instruction to be executed by P when it will be selected: re-test the synch. condition!
– Pattern:while(!synch_cond)
cond.wait();<access to resource>
Example: Bounded Mailbox
• Shared mailbox with capacity N• Monitor: circular message buffer (of size N)• Two entry operations to be executed in isolation
– void send(Message m) Cannot be accomplished if the buffer is full
– Message receive()Cannot be accomplished if the buffer is empty
Producer Thread
Consumer Thread
monitor circular_buffer{
messagge buffer[N];int occupied=0; int head=0; int bottom=0;condition not_full;condition not_empty;
public void receive(messagge m){ /*proc. entry -> mutually exclusive */
if (occupied==N) not_full.wait;buffer[code]=m;head=(head + 1)%N;occupied++;not_empty.signal;
}
public messagge send(){ /*proc. entry -> mutually exclusive */ messagge m;
if (occupied == 0) not_empty.wait; m=buffer[head];
bottom=(bottom + 1)%N; occupied--;
not_full.signal;return m;
}}
Synchronization in Java
• Global environment (shared data): threads interact/interfere by operating on shared objects– Competition: synchronized methods, locks– Cooperation: semaphores and wait-notify,
conditions• Package java.util.concurrent
Basic Monitor in Java
• JVM associates a lock to every object– States whether the object is free/occupied– Entry set queue for suspended threads
• Critical sections can be identified with the keyword synchronized– Synchronized methods– Synchronized sections in the code
Synchronized Section
• Compiler manages a synchronized section– Adding a prologue for acquiring the object’s lock• Lock free thread can execute the critical section• Lock busy thread suspended into the entry set queue
of the object
– Adding an epilogue for releasing the lock• No suspended thread lock released• Else lock maintained and assigned to one of the
suspended threads
Synchronized Block
synchronized(obj) { <code> }• <code> is a critical section for object obj• Mutual exclusion is guaranteed for obj w.r.t.– Other executions of the same block– Other synchronized blocks for the same object
<Object mutexLock = …>…public void M( ) {
<non-critical section>;synchronized (mutexlock){<critical section>;}<non-critical section>;
}
static synchronized void increment() {counter++;
}
• Synchronization is related to this (Counter object)• Mutual exclusion ensured for all synchronized methods
– E.g. also dec() method for Counter
Thread-Safe Counter
<lock acquisition or suspension>cur countercounter cur + 1<lock release or reassignment>
Byte code
Wait Set
• In addition to the entry set, each object is associated to another queue: wait set
• Special methods– wait(): insertion in the wait set– notify()/ notifyAll(): extraction from the
wait set– Can be invoked only by the thread owning the
object’s lock• Can be used only in a synchronized section
Wait and Notify(All)
• wait(): calling thread– Releases the lock – Is suspended in the wait set queue– N.B.: method throws InterruptedException
• notify(): one thread is selected from the wait set and moved into the entry set
• notifyAll(): all threads in the wait set are moved into the entry set
Policy: signal and continue!
Example: Bounded Mailbox• void send(Message m)
– Synchronized– Cyclic test (mailbox full wait())– After message insertion notify all
• Message receive()– Synchronized– Cyclic test (mailbox empty wait())– After message extraction notify all
• Is this efficient?
Producer Thread
Consumer Thread
Limitations of the Basic Monitor
• One queue for mutual exclusion (entry set)
• Only one queue for synchronizing threads on an object (wait set)
Conditions and Semaphors (from Java 5)
Java Semaphores
• Java (from 5.0) also explicitly supports semaphores (java.util.concurrent.Semaphore)
• Constructor: takes– Permits (no.): number of permits initially granted– Fairness (yes/no): if true, suspended threads will acquire
the resource in the order they asked for it• Basic methods– acquire() wait– release() signal
• Other useful methods (see JavaDoc)
Example: Bounded Mailbox
• How to realize it without a monitor, but only semaphores?
• How many semaphores?• How are they initialized?
Producer Thread
Consumer Thread
Other Useful Methods• sleep(long ms)
– Suspends thread for the specified amount of time• interrupt()
– Triggers an event that causes the interruption of thread• interrupted() isInterrupted()
– Check whether the current thread has been interrupted• join()
– Waits for the termination of the specified thread• isAlive()
– true if thread has been started and has not yet terminated its execution• yield()
– Forces thread to release CPU• Other useful methods: JavaDoc of Thread class
– E.g. Thread.getCurrentThread() returns the currently active thread
On Deprecated Methods• stop() forces thread termination
– All resources (e.g. locks) are instantaneously freed– If the thread was doing an “atomic” operation, the object’s state could
be left in an inconsistent state– The object can be now accessed by other threadShould not be used
• suspend() blocks a thread until resume() is invoked– Resources are not freed (e.g. locks are maintained)– If the thread has acquired a mutually exclusive resource (monitor), the
resource is blockedShould not be used
• In general, follow the “Java Thread Primitive Deprecation” guide (part of Java SE Documentation)
Thread-safe Datastructures
• Common data structures not thread-safe• LinkedList
• BlockingQueue• ConcurrentMap• CopyOnWriteArrayList
On Priorities
• Threads have two methods for priorities– setPriority(int v)
v [MIN_PRIORITY, MAX_PRIORITY]∈– getPriority()
• Java suggested best practice:– Among runnable threads, choose the ones of higher priority– Round robin over threads of the same priority– Interrupt thread if a thread of higher priority is runnable
• Some JVM implementations: delegate threads’ scheduling to O.S. behavior depends on JVM + OS
Use with care
Summary
• Java threads:– extend Thread– implement Runnable
• Synchronization an issue– Java provides techniques
• synchronized classes/methods/code snippets• semaphores• Synchronized data structures
top related