520 likes | 774 Views
Multi-Threading. Dr. M. Khamis. Thread-Based Multi-Tasking. Thread-based multi-tasking is about a single program executing concurrently several tasks e.g. a text editor printing and spell-checking text. Threads are lightweight tasks: 1) they share the same address space
E N D
Multi-Threading Dr. M. Khamis
Thread-Based Multi-Tasking • Thread-based multi-tasking is about a single program executing concurrently • several tasks e.g. a text editor printing and spell-checking text. • Threads are lightweight tasks: • 1) they share the same address space • 2) they cooperatively share the same process • 3) inter-thread communication is inexpensive • 4) context-switching from one thread to another is low-cost • Java multi-tasking is thread-based.
Reasons for Multi-Threading • Multi-threading enables to write efficient programs that make the maximum • use of the CPU, keeping the idle time to a minimum. • There is plenty of idle time for interactive, networked applications: • 1) the transmission rate of data over a network is much slower than the rate at which the computer can process it
Reasons for Multi-Threading • 2) local file system resources can be read and written at a much slower rate • than can be processed by the CPU • 3) of course, user input is much slower than the computer
Threads: Model • Thread exist in several states: • 1) ready to run • 2) running • 3) a running thread can be suspended • 4) a suspended thread can be resumed • 5) a thread can be blocked when waiting for a resource • 6) a thread can be terminated • Once terminated, a thread cannot be resumed.
Threads: Priorities • Every thread is assigned priority – an integer number to decide when to • switch from one running thread to the next (context-switching). • Rules for context switching: • 1) a thread can voluntarily relinquish control (sleeping, blocking on I/O, etc.),
Threads: Priorities • then the highest-priority ready to run thread is given the CPU. • 2) a thread can be preempted by a higher-priority thread – a lower-priority • thread is suspended • When two equal-priority threads are competing for CPU time, which one is • chosen depends on the operating system
Synchronization • In multithreading application more than one thread access data concurrently. • Ex. Assume 2-threads the first adds 500 to specific account and the other adds 900.
Race Condition • Thread 1, • Read the account balance to CPU register. • Add 500 to the content of the register. Then interrupted before register content is stored back into account • Thread 2 repeat what thread 1 done to add 900, then. • Thread 1 resume work to find the final account value is 5500 instead of 6400.
Threads: Synchronization • Multi-threading introduces asynchronous behaviour to a program. • How to ensure synchronous behaviour when we need it? • For instance, how to prevent two threads from simultaneously writing and • reading the same object? • Java implementation of monitors:
Threads: Synchronization • 1) classes can define so-called synchronized methods • 2) each object has its own implicit monitor that is automatically entered • when one of the object’s synchronized methods is called • 3) once a thread is inside a synchronized method, no other thread can call • any other synchronized method on the same object
Synchronization :using Lock object (called ReentrantLock) • Steps: • Defined Lock object (Lockob) as: • Lock lockob= new ReentrantLock(); • Use lockob with the Critical section as follow: Lockob.block() ; Try{ Critical section } Finally{ Lockob.unblock() ; }
The Methods of Lock class The Lock class exists in package called Java.util.concurrent.locks, has following methods: • void lock() Acquires this lock; blocks if the lock is currently owned by another thread • void unlock() Release this lock.
Constructors of ReentrantLock class The ReentrantLock class exists in Java.util.concurrent.ReentrantLock has the following constructors • ReentrantLock() • used to construct a reentrant lock to protect the critical section (default). • ReentrantLock(boolean fair) • As above constructor, but with fairness guarantee (has significant drag on performance).
Conditional Objects (Construction) • If thread, to enter section, needs condition to fulfilled in this case we use the conditional lock object (conditional variable). • Class bank Constructs array of double to keep account of the bank customers and to transfer amount of any account, it should check the corresponding account as follow: While (!(bank.getbalance(from)) >= amount) ; bank.transfer(from, to, amount) ;
Conditional Objects (Continued) While (!(bank.getbalance(from)) >= amount) ; // the thread should deactivated until account balance changes bank.transfer(from, to, amount) ; • Unless the thread blocks, it will wastes the CPU time and consumes quantum in busy waiting. • Defined Conditional Lock object (sufficientFunds) as follow: Lock lockob= new ReentrantLock(); Condition sufficientFunds= lockob.newCondition()
Conditional Objects (how to use?) lockob.lock() ; Try{ While (!(bank.getbalance(from)) >= amount) sufficientFunds.await() ;// deactivate the thread (waiting.. Not Runnable) bank.transfer(from, to, amount) ; sufficientFunds.signallAll() ;//reactivate waiting threads (runnable again) } finally { lockob.unlock() ; } • Lock object can have one or more conditional objects. The new condition on lock object is obtained by calling new lockob.newCondition() ;
Conditional Lock and Deadlock • Waiting thread waits until another thread executing signallAll(), if no such thread then the thread will wait indefinitely (program hangs). • In the above example the waiting threads take another chance to inspect the condition when the accounts change.
Conditional Lock and Deadlock • Signal(): Activating only one thread which is chosen randomly (more efficient) and the plenty is the danger of finding the selected thread itself blocked as the condition to continue is not satisfied yet (leads to deadlock). • N.B. The Thread Can Only call await(), signallAll, or signal() when it owns the lock of the condition.
Conditional Lock • Let every thing goes right but the price is the program will run more slower than before using the lock. • Using the Lock object in precise manner is challenging since it can lead to deadlock. • API of java.util.concurrent.locks.lock • Condition newCondition() Return a condition object that is associated with lock
API java.util.concurrent.locks.Condition • void await() Put the thread on wail set for this condition. • void signalAll() Unblock all threads in the wait set for this condition. • void signal() Unblock one random thread from the wait set for this condition.
Summary of Lock • Protects section of code, allowing only one thread to execute code at time. • Lock can have one or more conditional lock. • Each conditional object manages threads that have entered a protected code section but they cannot proceed.
Synchronized Keyword and its Equivalent Each object in java has intrinsic lock object. If a method is declared with keyword “synchronized” , then the object lock protect the whole method, as follow: public synchronized void method(){ method body… } public synchronized void method(){ Try{ this.intinisic.lock(); mehod body….. }finally{ this.intrinsic.unblock() ;}
Synchronized Keyword • It is legal to declare static method with “synchronized” • The transfer method declaration with “synchronized” public synchronized void transfer(int from, int to,doublr amount){ while (account[from] < amount) wait() ; account[from] -= amount ; account[to]+= amount; notifyAll() ; }
Limitations of Intrinsic Lock • You cannot interrupt thread that is trying to acquire a lock. • You cannot specify a timeout when trying to acquire a lock. • Having a single condition per lock can be inefficient
What you should use in your code? • If synchronized keyword works with you use it as you will write less code and less room for error • Use lock/condition if you need additional power that this constructs give you.
API java.lang.object • void notifyAll(); Unblocks all threads that called wait on this object. This is called only from within synchronized method. • void wait() Wait thread until it is notified. Called only from within synchronized method. • void wait(long msec) • void wait(long msec, int nsec)
API java.lang.object • void notify() Unblocks one thread selected randomly from the threads wait on this object. This is called only from within synchronized method. All the above methods throws IllegalMonitorStateException if the current thread is not the owner of the object’s lock.
Read-Write Lock Class ReentrantReadWriteLock is used to allow threads sharing data for read and write . Some thread that read has to continue while those threads to write have to implement mutual exclusion.
Steps of read write lock • Construct ReentrantReadWriteLock object. • ReentrantReadWriteLock rwl= new ReentrantReadWriteLock() ; • Extract read and write locks as follow: • private lock readlock= rwl.readLock(); • Private lock writelock= rwl.writeLock();
Example • Use read lock in all accessors : public double gettotalbalance(){ readlock.lock() Try{ ……. }finally{ readlock.unlock() ; } }
Example • Use write lock in mutators public double transfer(){ rwritelock.lock() Try{ ……. }finally{ writelock.unlock() ; } }
Synchronized block • Every java object has a lock, a thread can acquire a lock by calling synchronized method. There is second mechanism for acquiring the lock, by entering a synchronized block. This is done as: synchronized(obj){ critical section }
Example public class Bank{ object obj= new object(); double [] accounts; public void transfer(){ synchronized(obj) { account[from]-= account[from] ; account[to]+= account[to] ; } } }
Lock testing and time out • A thread wait indefinitely when it calls the lock() method to acquire lock which is acquired by another thread. • tryLock() method :tries to acquire a lock and return true if it was successful. Otherwise, it immediately returns false and the thread go off and do something else.
Example If (mylock.tryLock()){ //now thread owns the lock… Try {….} Finally{ mylock.unlock(); } }else { //do something else }
Lock testing and time out • mylock.trylock(100,TimeUnit.MILLISECONDS) • Time unit is enumeration SECONDS,MILLISECONDS, MICOSECONDS, NANOSECONDS • If thread is interrupted while it waiting to acquire lock, the interrupted thread continues to be blocked until the lock is avialable.
Lock testing and time out • If trylock() is interrupted with timeout, then InterruptedException is thrown. This is useful because it causes the program to break the deadlock. • lockInterruptibly() method is used as trylock() method with infinite timeout. • When you wait on condition, also time out can be used mycondition.await(100, TimeUnit.MILLISECONDS)
Lock testing and time out • This await method returns, if another thread has activated this thread by call signal() or signallAll(), or the time out is elapsed.
API • boolean trylock() Tries to acquire lock without blocking; if lock is available even if fair locking and other threads have been waiting.
API • boolean trylock(long time, TimeUnit time) Tries to acquire lock blocking not more than the given time, return true if it successful • void lockInterruptibly() Tries to acquire lock blocking indefinitely, throws exception if the thread is interrupted.
API • boolean await(long time, TimeUnit time) Enter wait set for this condition and removed when time is elapsed or signalled by another thread.return false in case of time out and false otherwise • void awaitUnInterruptibly() Enter wait set for a condition until thread is removed from the wait set if thread is interrupted this method doesn,t throws exception.
Blocking Queue • If you want to stay away from low level implementation of implementing mutual execution for the critical section, you have to use higher level implementation such as blocking queue. • Useful in case of producer consumer. • Instead of performing the transfer directly; the transfer thread put the transfer object on a queue and another thread remove objects from the queue and carries out the transfers.
Blocking Queue • No synchronization is necessary, the implementation of threadsafe queue classes had to worry about the lock, not you. • Useful for coordination between multiple threads. • Blocking queue cause the thread to wait when it tries to add element in case of fullness of the queue. Also when thread need to remove object of the empty queue.
Blocking Queue • It balance load by this way between producers and consumers. • Add(), element(), offer(), peek(), poll(), put(), remove() and take(). All are defined methods for the blocking queue.
Blocking Queues • There is variations of offer and poll methods with timeout: Object head = q.poll() ;
Monitor Concept • Locks and Conditions are very powerful for thread synchronization, but they are not object oriented. • On the contrary Monitor has the following characteristics: • Class with only private fields. • Each object of this class has associated lock. • All methods are synchronized by that lock. • Lock can have any number of conditions.