Multithreading
Objectives Need for Multithreading Life Cycle of a Thread Understand Multitasking Need for Multithreading Implementing Multithreading in Java Life Cycle of a Thread Understanding Thread Priorities Synchronization Inter-thread Communication
Multitasking Multitasking is a process that involves multiple tasks running simultaneously. OS implements Multitasking using Multiprocessing. Java implements Multitasking using Multithreading.
Multiprocessing Program is a set of instructions and a Process is a ‘Running Instance of a Program’. CPU is shared between 2 processes.
Multiprocessing In Multiprocessing, OS implements Context Switching mechanism. Program’s entire context including variable, global variables, methods etc. is stored separately.
Multithreading Different tasks within a main task execute simultaneously. Multithreading implements the idea of Multitasking by taking it one level lower.
Multithreading Individual programs appear to do multiple tasks simultaneously. Each sub task within an application is called as a Thread.
Thread & Its Need A Thread is an entity within a Process. It defines the path of execution. Need: To run multiple tasks simultaneouly. To make effective use of CPU. In Java, by default, ‘main()’ is one thread and ‘Garbage Collector’ is another thread.
Process and Thread Each process has a complete set of its own variables. It takes more overhead to launch a new process. Inter-process communication is a heavyweight activity. Threads live in a single application, thus may share the same data. It takes much less overhead to create and destroy a thread. Inter-thread communication is a lightweight activity.
Implementing Multithreading in Java Multithreading in Java can be implemented by using one of the following approaches: Extending Thread class. Implementing Runnable interface.
Life Cycle of Thread start sleep interval expires IO Complete resume BORN start sleep interval expires IO Complete READY resume notify/notifyAll suspend RUNNING wait sleep IO Request WAITING SLEEPING BLOCKED SUSPENDED stop complete DEAD
Thread Priorities Thread Priorities are used by Scheduler. Threads of equal priority complete equally for CPU. The scheduler picks up the highest priority thread.
Thread Priorities Priority levels can be set within the range MIN_PRIORITY(1) and MAX_PRIORITY(10). Default priority is NORM_PRIORITY(5).
Methods of Thread Class start() stop()//Deprecated yield() isAlive() sleep() suspend()//Deprecated resume()//Deprecated currentThread() join()
start() A method that makes a request to OS for the creation of the Thread. Responsible for transitioning of the thread from BORN state to READY state.
stop() - Deprecated Forcefully kills the thread. Sends the thread into DEAD state. Once a thread becomes DEAD, cannot be started again.
yield() A static method that causes currently executing thread to yield the control. If there are other runnable threads whose priority is at least as high as this thread, they will be scheduled next. Again, everything is dependent upon OS.
isAlive() Returns true if a thread has started and not yet terminated. A thread is dead if run() method executes normally. It dies abruptly because of an uncaught exception.
sleep() A static method that sends a thread into the ‘sleeping’ state. A thread remains in the ‘sleeping’ state until the sleep time interval is over. Time interval is specified in terms of milliseconds.
suspend() and resume() - Deprecated Sends a thread into the ‘suspended’ state. Deprecated as the transitioning into the READY state is implementation dependent. resume(): Brings the thread into the ‘ready’ state from the suspended state.
currentThread() A method that returns a reference of the currently running thread. E.g. public void run(){ if(Thread.currentThread() == t1){ //Some Code }
join() Waits for a thread to terminate. E.g. public void myMethod()throws Exception{ Thread t = ……..; t.join(); //These statements execute only after the death of Thread t. }
Synchronization
Synchronization Many times, 2 or multiple threads need to share access to the same object. This needs to ensure that the object will be modified by only one thread at a time, else they will fall into ‘race condition’.
Synchronization Key to synchronization is the concept of monitor. A monitor is an object that is used as a mutually exclusive lock. Only one thread can own a monitor at a given time. When a thread acquires a lock, it is said to have entered the monitor. All other threads attempting to enter the locked monitor will get suspended, until the first thread exits the monitor.
Inter-Thread Communication
Inter-Thread Communication Sometimes, in an application there is a need of 2 or multiple threads interacting with each other. It leads to inter-thread communication. E.g. a communication between 2 threads like: Producer and Consumer or Feeder and Copier.
Inter-Thread Communication To implement inter-thread communication, there are 3 methods used: wait() notify() notifyAll()
wait() Must be invoked within a synchronized context. When invoked, releases the lock and sends the currently running thread into the ‘waiting’ state. Gives a chance to other threads looking for the same lock.
notify() & notifyAll() Wakes up a single thread that is in ‘waiting’ state. If multiple threads are waiting, then the thread that enters first into the ‘waiting’ state gets notified. notifyAll() Wakes up all threads.
DEADLOCKS When a thread enters the ‘waiting’ state, cannot be unblocked itself. The ‘waiting’ thread can be brought into READY state when other thread notifies by using either notify() or notifyAll(). If not handled properly, all the threads may go into the ‘waiting’ state and there is no one to notify them. This leads to DEADLOCK.