Monday, 15 September 2014

Threads in Java


What is Thread ?
A thread is an independent sequential path of execution within a program


Race Condition:
A race condition occurs when two or more threads simultaneously update the same value, and as a consequence, leave the value in an undefined or inconsistent state.


Thread Creation:
1.Inheritence- Heavy Implementation of Thread
extending the java.lang.Thread class
2.Interface- Light Version of Thread Creation
implementing the java.lang.Runnable  interface


Thread States:

Thread is a lightweight process, the smallest unit of scheduled execution. Instance of the Thread class in Java 6 could be in one of the following states:
  • new,
  • runnable,
  • timed waiting,
  • waiting,
  • blocked,
  • terminated.
These states are Java Virtual Machine (JVM) states reported by JVM to Java programs. At any given point in time thread could be in only one state.





Protocol state machine example - Thread states and life cycle in Java 6
New is the thread state for a thread which was created but has not yet started.
At the lower operating system (OS) level, JVM’s runnable state could be considered as a composite state with two substates. When a thread transitions to the runnable JVM state, the thread first goes into the ready substate. Thread scheduling decides when the thread could actually start, proceed or be suspended. Thread.yield() is explicit recommendation to thread scheduler to pause the currently executing thread to allow some other thread to execute.
A thread in the runnable state is executing from the JVM point of view but in fact it may be waiting for some resources from the operating system.
Timed waiting is a thread state for a thread waiting with a specified waiting time. A thread is in the timed waiting state due to calling one of the following methods with a specified positive waiting time:
  • Thread.sleep(sleeptime)
  • Object.wait(timeout)
  • Thread.join(timeout)
  • LockSupport.parkNanos(timeout)
  • LockSupport.parkUntil(timeout)
A thread is in the waiting state due to the calling one of the following methods without timeout:
  • Object.wait()
  • Thread.join()
  • LockSupport.park()
Note, that thread in the waiting state is waiting for another thread to perform a particular action. For example, a thread that has called Object.wait() on an object is waiting for another thread to call Object.notify() or Object.notifyAll() on that object. A thread that has called Thread.join() is waiting for a specified thread to terminate. It means that waiting state could be made a composite state with states corresponding to these specific conditions.
Thread is in the blocked state while waiting for the monitor lock to enter a synchronized block or method or to reenter a synchronized block or method after calling Object.wait().
A synchronized statement or method acquires a mutual-exclusion lock on behalf of the executing thread, executes a block or method, and then releases the lock. While the executing thread owns the lock, no other thread may acquire the lock and is blocked waiting for the lock.
After thread has completed execution of run() method, it is moved into terminated state.



Thread Priorities:

Thread has its own priority depends on the priority we set to thread. If not priority set to thread then it will take DEFAULT_PRIORITY( which is 5). Priority starts from 1-10. where 10 is high priority.
But notable thing here is , we cannot guaranteed that threads can be executed in the order of priority or on priority basis. It all depends on the Thread Scheduler to pick and manage .


Thread WAIT States:

Thread will go to WAITING state depends on the functions we call on threads. We have methods like sleep(x),wait(x),yield(),join(x) to make thread to take some rest or give the priority to other threads.

Sleep ->
When we call sleep on thread , it will go to TIMED_WAITING state and will not give a chance to run other thread. While sleeping , thread will not release the lock .
*  you can reach this site for differences between sleep and yield and wait.

WAIT() & NOTIFY()
When a thread calls the wait() method:
  1. The thread releases the lock for the object.
  2. The state of the thread is set to blocked.
  3. The Thread is placed in the wait set for the object

When a thread calls the notify() method:
  1.  An arbitrary thread is picked from the list of threads in the wait set.
  2. Moves the selected thread from the wait set to the entry set.
  3. Sets the state of the selected thread from blocked to runnable.


Wait ,Notify and NotifyAll are called inside the synchronized block because this mechanism is used for inter-thread communication. These methods are instance methods in Object class because java by default providing the feature of waiting on every user defined class which extends Object.
Wait will not the keep the LOCK, only sleep will keep the LOCK when it is in sleeping/TIMED_WAITING state.Locks are made available on per Object basis.


Starvation
Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads. For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked.

• Causes of Starvation in Java
Threads with high priority swallow all CPU time from threads with lower priority
Threads are blocked indefinitely waiting to enter a synchronized block
Threads waiting on an object (called wait() on it) remain waiting indefinitely

How to Avoid Starvation:

Fairness-
Use Locks with proper time out.



Locks & Conditions
These are improvised version from synchronized blocks which gives fairness and reentrance.


ReentrantLock

The same thread can acquire the same lock multiple times, but you have to make sure you release the lock the same number of times that you acquire it. This Feature we cannot achieve using synchronization. TO achieve fairness with this,
The constructor for this class accepts an optional fairness parameter. When set true, under contention, locks favour granting access to the longest-waiting thread. Otherwise this lock does not guarantee any particular access order. Programs using fair locks accessed by many threads may display lower overall throughput (i.e., are slower; often much slower) than those using the default setting, but have smaller variances in times to obtain locks and guarantee lack of starvation. Note however, that fairness of locks does not guarantee fairness of thread scheduling. Thus, one of many threads using a fair lock may obtain it multiple times in succession while other active threads are not progressing and not currently holding the lock. Also note that the untimed tryLock method does not honour the fairness setting. It will succeed if the lock is available even if other threads are waiting.

Locks can use Fairness policy if set true in constructor.
It is recommended practice to always immediately follow a call to lock with a try block, most typically in a before/after construction such as:
 class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...
public void m() {
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }



Difference between ReentrantLock and synchronized keyword in Java
Though ReentrantLock provides same visibility and orderings guaranteed as implicit lock, acquired by synchronized keyword in Java, it provides more functionality and differ in certain aspect. As stated earlier,  main difference between synchronized and ReentrantLock is ability to trying for lock interruptibly, and with timeout. Thread doesn’t need to block infinitely, which was the case with synchronized. Let’s see few more differences between synchronized and Lock in Java.
  1.  Another significant difference between ReentrantLock and synchronized keyword is fairness. synchronized keyword doesn't support fairness. Any thread can acquire lock once released, no preference can be specified, on the other hand you can make ReentrantLock fair by specifying fairness property, while creating instance of ReentrantLock. Fairness property provides lock to longest waiting thread, in case of contention.

  1.  Second difference between synchronized and Reentrant lock is tryLock() method. ReentrantLock provides convenient tryLock() method, which acquires lock only if its available or not held by any other thread. This reduce blocking of thread waiting for lock in Java application.

  1.  One more worth noting difference between ReentrantLock and synchronized keyword in Java is, ability to interrupt Thread while waiting for Lock. In case of synchronized keyword, a thread can be blocked waiting for lock, for an indefinite period of time and there was no way to control that. ReentrantLock provides a method called lockInterruptibly(), which can be used to interrupt thread when it is waiting for lock. Similarly tryLock() with timeout can be used to timeout if lock is not available in certain time period.

  1.  ReentrantLock also provides convenient method to get List of all threads waiting for lock.

So, you can see, lot of significant differences between synchronized keyword and ReentrantLock in Java. In short, Lock interface adds lot of power and flexibility and allows some control over lock acquisition process, which can be leveraged to write highly scalable systems in Java.



7 comments:

Please comment here