Title: Web Programming Course
1Web Programming Course
- Lecture 4 Concurrent Programming 1
2Concurrent Programming
- What is a concurrent program?
- A sequential program has a single flow.
- A concurrent program has multiple flows.
- Allows to perform multiple computations in
parallel - Allows to control multiple external activities
occurring at the same time. - Programming paradigm expressing the natural
potential parallelism and solving the resulting
synchronization and communication problems
3Main Motivation CPU Utilisation
Response time in seconds
4Parallelism Between CPU and I/O Devices
5Sequential Maze Search
6Concurrent Maze Search
7Why Concurrent Programming?
- To allow the expression of potential parallelism,
such that more than one computer can be used to
solve the problem - To model the parallelism in the real world
- Many real-life systems are inherently concurrent,
as devices operate in parallel in the real world - Performance gain from multiprocessing hardware
- Application throughput and responsiveness
- an I/O call partially blocks functionality
- handling user requests
8Terminology
- Process is a sequential program, i.e. a sequence
of statements executed one after another - Unofficially, instance of program
- Each process has a single thread of control
- A concurrent program is a collection of
autonomous sequential processes, executed
(logically) in parallel
9Terminology
- The actual implementation (i.e. execution) of a
collection of processes usually takes one of
three forms - Multiprogramming processes multiplex their
executions on a single processor - Multiprocessing processes multiplex their
executions on a multiprocessor system where there
is access to shared memory - Distributed Processing processes multiplex
their executions on several processors which do
not share memory
10Common Concurrent Applications
- Web Services
- I/O processing
- Simulations
- GUI-based applications
- Real-time systems
- Embedded systems
- Mobile code
11Process Creation and Termination
- Principal events causing process creation
- Execution of a process creation system call
- System initialization
- User request to create a new process
- Tree-like structure of processes is managed by OS
- Conditions which terminate processes
- Normal exit (voluntary)
- Error exit (voluntary)
- Fatal error (involuntary)
- Killed by another process (involuntary)
12Scheduling Processes
- Processes are managed by OS process called
scheduler - Well-known scheduling policies include
- First Come First Served
- Shortest Job First
- Priorities Scheduling
- Round Robin
- and their combinations
13Context Switch
- Storing the data of the current process and
loading the data of the next process
14Process States
15Challenges
- Concurrent programs are harder to get right
- Communication send or receive information
- Synchronization wait for another process to act
- Atomicity do not stop in the middle
- Some problems are inherently sequential
- E.g., computations waiting for the output of
previous computations
16Why is Concurrent Programming Hard?
- Non-Determinism
- Deterministic two executions on the same input
it always produce the same output - Non-deterministic two executions on the same
input may produce different outputs - Why does this cause difficulty?
- May be many possible executions of one system
- Hard to think of all the possibilities
- Hard to test since some errors occur infrequently
17Non-Determinism
- Interleaving execution order
- Consider the following program
- What are the possible interleavings?
p1a p1b p2a p2b p2a p2b p1a p1b p1a p2a
p1b p2b p2a p1a p2b p1b p1a p2a p2b
p1b p2a p1a p1b p2b
18Non-Determinism
- Consider the following program
- What are the possible values of c1 and c2 after
execution of the program?
Two possible answers c1 9 c2 3 if p1
executes before p2 c1 15 c2 3 if p2
executes before p1
19Coordination Between Processes
- Critical section
- Two processes may access shared resource
- Inconsistent behavior if two actions are
interleaved - Allow only one process in critical section
- Deadlock
- Process may hold some locks while awaiting others
- Deadlock occurs when no process can proceed
20Processes in Java
- To create a new process
- Runtime.GetRuntime().exec(String command)
- Platform-dependent functionality
- Returns reference to Process object
- To terminate a process
- System.exit(int status)
- Other process can be killed by destroy()
21Processes in Java
- The following methods may be used to pass
information between processes - OutputStream getOutputStream()
- InputStream getIntputStream()
- InputSteam getErrorStream()
- waitFor() waits for another process to end.
Returns its exit value (0-success, other-failure) - exitValue() gets exit value of a process
22Example
- public class Runner
- final static String JAVA_PATH
"C\\JBuilderX\\jdk1.4\\bin\\" - final static String Prog_PATH
"C\\JBuilderX\\jbprojects\\Tester\\classes\\" - public static void main(String args)
- try
- Process hello null
- String cmdJAVA_PATH"java -classpath
"Prog_PATH" HelloWorld" - System.out.println("CMD"cmd)
- hello Runtime.getRuntime().exec(cmd)
- int exitValue hello.exitValue()
- System.out.println("The exit value is "
exitValue) -
- catch (Exception ex)
- System.out.println (ex)
-
-
Try inserting here hello.waitFor()
23Example
- public class HelloWorld
- public static void main(String args)
- System.out.println("Hello World")
- System.exit(0)
-
-
- The output is
- java.lang.IllegalThreadStateException process
has not exited - Scheduling is needed!
- After inserting hello.waitFor() the output
is The exit value is 0
24Thread Model
- Thread is a set of instructions to be executed
one at a time, in a specified order - Often called Light-Weight Process
- Threads of one given process share the same
address space - Context-switch is simpler
- Can read and write the same memory
25Single and Multithreaded Processes
26Threads vs. Processes
- Creating threads is cheaper than processes
- Context switch is faster
- Inter-thread communication
- In general is easier
- Sometimes, may be very complicated
- Allow independent execution flows
- Simpler blocking handling
- Inherently supported by Java API
27Example Multi-Threaded Server
- Single-threaded server can not process multiple
requests - In multi-threaded server
- Manager thread recognized incoming requests
- The requests are handled by worker threads
- Better availability is achieved
28Java Thread States
29Java Thread States
- Java threads are managed by the JVM.
- As a thread is launched, it is registered with
the JVM thread scheduler. - Threads are launched using start() method
- Wraps call to run() method
- start() can be called only once
- Also, tree-like structure of threads
- Scheduler determines which thread will run in the
CPU at any given point of time - When a thread gets CPU, run() method is executed
30Java Thread States
- The suspend() method allows a thread to make
another thread un-runnable. - The suspended thread becomes runnable when some
other thread resumes it using the resume()
method. - The stop() method allows a thread to kill another
thread.
31Java Thread States
- When the run() method ends the execution is
considered completed and the thread is considered
dead. - A dead thread cannot be started again
- But it still exists and like any other object,
its methods and data can be accessed.
32Threads Scheduling
- Each thread has a numeric priority
- Between Thread.MIN_PRIORITY and
Thread.MAX_PRIORITY - In Java, these are respectively 1 and 10
- The JVM implicitly creates a thread (named main
thread) when executing program main()method - Main has default priority Thread.NORM_PRIORITY
(5) - New thread has same priority as thread created it
- Accessing priorities via getPriority() and
setPriority() - All the ready threads contend for the CPU time
- Scheduler gives preference to higher-priority
threads
33Java Threads Implementation
- New threads may be created in Java by
- Extending Thread class
- Implementing Runnable interface
- They are descendants of the main thread
34Implementing Runnable Interface
- The class implements an interface called Runnable
interface, which defines a single abstract method
run(). - package java.lang
- public interface Runnable
- public void run()
35Implementing Runnable Interface
- When a class implements Runnable interface, it
provides an implementation of the run() method. - public class ConcurrentReader implements Runnable
- ...
- public void run()
- / code here executes concurrently with the
caller / -
- ...
36Implementing Runnable Interface
- To start the thread, you need to create an object
of type Runnable, bind it to a new Thread object,
and then start it. - Calling start()
- Creates the thread data structures
- Invokes the run() method of the Runnable object
as the first procedure on that new thread.
37Implementing Runnable Interface
- The java.lang.Thread class has a constructor that
takes an object of type Runnable - Thread(Runnable object)
- This constructor must be provided an object that
implements Runnable interface - i.e., contains an implementation of run() method
38Implementing Runnable Interface
- ConcurrentReader readerThread new
ConcurrentReader() - Thread t new Thread(readerThread)
- // create thread using a Runnable object
t.start() - // automatically calls ConcurrentReader.run()
39Implementing Runnable Interface
class Interleave public static int c1 2
public static int c2 3 public static void
main (String args) Thread p1 new
Thread(new P1()) Thread p2 new Thread(new
P2()) p1.start () p2.start ()
class P1 implements Runnable public void run
() Interleave.c1 Interleave.c1
Interleave .c2 class P2 implements
Runnable public void run ()
Interleave.c1 Interleave.c1
Interleave.c2
Sometimes it is desirable to implement the run()
method in a class implementing interface Runnable.
40Extending Thread Class
- Alternatively, we can define a subclass of the
class Thread directly. - class ConcurrentWriter extends Thread
- public void run()
- //provide the code to run as a //separate
thread of control -
41Extending Thread Class
- To start this thread you just need to do the
following - ConcurrentWriter writerThread new
ConcurrentWriter() - writerThread.start()
- // start calls run() automatically
42Extending Thread Class
class Interleave public static int c1 2
public static int c2 3 public static void
main (String args) Thread p1 new P1 ()
Thread p2 new P2 () p1.start () p2.start
()
class P1 extends Thread public void run ()
Interleave.c1 Interleave.c1 Interleave
.c2 class P2 extends Thread public void
run () Interleave.c1 Interleave.c1
Interleave.c2
Usually, it is easier to extend the Thread class
and override its run() method.
43Extending Thread Class Example
- class MyThread extends Thread
- private String message
- public MyThread(String m) messagem
- public void run()
- for(int r0 rlt20 r)
System.out.println(message running ...) -
-
-
- public class ThreadRunner
- public static void main(String args)
- MyThread t1,t2
- t1new MyThread(1st thread")
- t2new MyThread(2nd thread")
- t1.start()
- t2.start()
-
44Possible Output
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 2nd thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
- 1st thread running ...
There is no guarantee for the order of outputs,
since the threads are concurrent
45Thread Priority Example
- class A extends Thread
-
- public void run()
-
- System.out.println("Thread A
started") - for(int i1ilt4i)
- System.out.println("\t From
ThreadA i "i) -
- System.out.println("Exit from
A") -
-
- class B extends Thread
-
- public void run()
-
- System.out.println("Thread B
started") - for(int j1jlt4j)
- System.out.println("\t From
ThreadB j "j) -
46Thread Priority Example
- class C extends Thread
-
- public void run()
-
- System.out.println("Thread C
started") - for(int k1klt4k)
- System.out.println("\t From
ThreadC k "k) -
- System.out.println("Exit from
C") -
-
- class ThreadPriority
-
- public static void main(String args)
- A threadAnew A()
- B threadBnew B()
- C threadCnew C()
- threadC.setPriority(Thread.MAX
_PRIORITY) - threadB.setPriority(threadA.ge
tPriority()1)
47Thread Priority Example
- Started Thread A
- Started Thread B
- Thread B started
- From ThreadB j 1
- From ThreadB j 2
- From ThreadB j 3
- From ThreadB j 4
- Exit from B
- Started Thread C
- Thread C started
- From ThreadC k 1
- From ThreadC k 2
- From ThreadC k 3
- From ThreadC k 4
- Exit from C
- End of main thread
- Thread A started
- From ThreadA i 1
- From ThreadA i 2
48Extending vs. Implementing
- Why does Java allow two different ways to provide
thread objects? - How do you decide when to extend the Thread class
versus implementing the Runnable interface? - Java only allows single class inheritance, so if
a class inherits from another class, but also
needs to run as a thread, then it extensd the
other class and implements the Runnable
interface. - So, it is quite common for a class X to extend
some class Y and implement the Runnable interface
49Extending vs. Implementing
- class X extends Y implements Runnable
- public void do_it()
- //the code to run as a thread of control
-
- public void run() do_it() // can be run
a thread if needed
50Extending vs. Implementing
- By implementing Runnable interface, rather than
extending the Thread class, you declare that an
object of type X will run as a thread - But not always it has to run as a thread.
- Since all the run() method does, in this case, is
call another public method that could be called
without running a thread, it gives the user the
option of either having an object of type X run
concurrently, or sequentially.
51Extending vs. Implementing
- X obj new X()
- obj.do_something() // runs sequentially in the
current thread - Thread t new Thread(new X()) // create X and
run as a separate thread - t.start() // start() calls run() which calls
do_it()
52Thread class
- public static Thread currentThread()
- public static void dumpStack()
- public final void setName( String name )
- public final String getName()
- public final void setPriority( int newPriority )
- public final int getPriority()
- public final native boolean isAlive()
- public void start()
- public final void suspend()
- public final void resume()
- public final void stop()
- public static void sleep(long millis )
- public static void yield()
- public void join()
53public static Thread currentThread()
- Static methods that returns a reference to the
currently running thread -
- try
- System.out.println( Thread.currentThread().getNam
e() -
- catch(InterruptedException e)e.printStackTrace()
54public static void sleep(long millis )
- Causes a thread to be blocked for a given time
- Afterwards, it becomes ready
- try
- Thread.sleep(1000)
-
- catch(InterruptedException e)e.printStackTrace()
- It is unknown whether the thread will get the CPU
as soon it becomes ready. It just starts
contending for the CPU time with the other
threads.
55sleep() Example
- class MyThread extends Thread
- private String message
- public MyThread(String m) messagem
- public void run()
- for(int r0 rlt20 r)
- try
- System.out.println(message running ...)
- Thread.sleep((long) 100)
-
- catch (InterruptedException e)
-
- // end of for
- // end of run
- // end of class
56Output
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
- 2nd thread running ...
- 1st thread running ...
57public final boolean isAlive()
- Returns true as long as a thread is not dead
- Blocked thread is not dead!
- MyThread executive new MyThread(thread1")
- executive.start()
- if (executive.isAlive())
- //do something
- else
- //do something else
58public void join()
- The execution continues only when the thread is
dead - MyThread executive new MyThread(thread1")
- executive.start()
- try
- executive.join()
- catch(InterruptedException e)e.printStackTrace()
59public static void yield()
- Causes the thread to voluntarily release the CPU
for a thread with the same (or higher) priority - Only a recommendation for the scheduler
- try
- while(! cobdition)
- Thread.currentThread().yield()
-
- catch(InterruptedException e)e.printStackTrace()
60Memory Management
- Shared memory objects are managed in the address
space of the process. - Every thread separately manages registers and
program counter. - Every thread manages its own memory address space
on a heap. - Calling methods within thread uses stack.
61Memory Management
- class Worker implements Runnable
- Object arg, other
- Worker(Object a)
- arg a
-
- public void run()
- Object tmp new Object()
- other new Object()
- for(int i 0 i lt 1000 i)
- // do something
-
62Memory Management
- class Demo
- static public void main(String args)
- Object shared new Object()
- Runnable worker1new Worker(shared)
- Thread t1 new Thread(worker1)
- Runnable worker2 new Worker(shared)
- Thread t2 new Thread(worker2)
- t1.start()
- t2.start()
- // do something here
-
63Memory Management
64Whats the Problem
- Both threads use shared
- What happens if both of them access it
concurrently? - E.g., both of them try to modify it?
- Synchronization is needed!