Showing posts with label Threads. Show all posts
Showing posts with label Threads. Show all posts

Tuesday, May 24, 2011

Volatile Keyword

What does volatile do?

This is probably best explained by comparing the effects that volatile and synchronized have on a method. volatile is a field modifier, while synchronized modifies code blocks and methods. So we can specify three variations of a simple accessor using those two keywords:

         int i1;  
int geti1() {return i1;} volatile int i2;
int geti2() {return i2;} int i3; synchronized int geti3() {return i3;}

geti1() accesses the value currently stored in i1 in the current thread. Threads can have local copies of variables, and the data does not have to be the same as the data held in other threads. In particular, another thread may have updated i1 in it's thread, but the value in the current thread could be different from that updated value. In fact Java has the idea of a "main" memory, and this is the memory that holds the current "correct" value for variables. Threads can have their own copy of data for variables, and the thread copy can be different from the "main" memory. So in fact, it is possible for the "main" memory to have a value of 1 for i1, for thread1 to have a value of 2 for i1 and for thread2 to have a value of 3 for i1 if thread1 and thread2 have both updated i1 but those updated value has not yet been propagated to "main" memory or other threads.

On the other hand, geti2() effectively accesses the value of i2 from "main" memory. A volatile variable is not allowed to have a local copy of a variable that is different from the value currently held in "main" memory. Effectively, a variable declared volatile must have it's data synchronized across all threads, so that whenever you access or update the variable in any thread, all other threads immediately see the same value. Of course, it is likely that volatile variables have a higher access and update overhead than "plain" variables, since the reason threads can have their own copy of data is for better efficiency.

Well if volatile already synchronizes data across threads, what is synchronized for? Well there are two differences. Firstly synchronized obtains and releases locks on monitors which can force only one thread at a time to execute a code block, if both threads use the same monitor (effectively the same object lock). That's the fairly well known aspect to synchronized. But synchronized also synchronizes memory. In fact synchronized synchronizes the whole of thread memory with "main" memory. So executing geti3() does the following:

  1. The thread acquires the lock on the monitor for object this (assuming the monitor is unlocked, otherwise the thread waits until the monitor is unlocked).
  2. The thread memory flushes all its variables, i.e. it has all of its variables effectively read from "main" memory (JVMs can use dirty sets to optimize this so that only "dirty" variables are flushed, but conceptually this is the same. See section 17.9 of the Java language specification).
  3. The code block is executed (in this case setting the return value to the current value of i3, which may have just been reset from "main" memory).
  4. (Any changes to variables would normally now be written out to "main" memory, but for geti3() we have no changes.)
  5. The thread releases the lock on the monitor for object this.

So where volatile only synchronizes the value of one variable between thread memory and "main" memory, synchronized synchronizes the value of all variables between thread memory and "main" memory, and locks and releases a monitor to boot. Clearly synchronized is likely to have more overhead than volatile.

Sunday, December 12, 2010

Is this Thread Safe II

Is the given code thread safe?


public class Test {
private static int count = 0;
private static final Object lock= new Object();
public synchronized void foo() {
count++;
}
}


Though at first it looks thread safe but it is not as the counter is a static field and to provide atomicity we need to hold a lock on the class object. So there 4 ways of doing it

1) To make the method static


public static synchronized void incrementCount() {
count++;
}


2) To take lock on the Class object explicitly


public void incrementCount() {
synchronize (Test.class) {
count++;
}
}


3) To take a lock on another static Object


private static final Object countLock = new Object();

public void incrementCount() {
synchronize (countLock) {
count++;
}
}


4) Use the new AtomicInteger object from the java.util.concurrent.atomic package


private final static AtomicInteger count = new AtomicInteger(0);

public void foo() {
count.incrementAndGet();
}

Sunday, December 5, 2010

IS this Thread Safe

I found this question in one of the forums so thought of sharing it

In the class below, is method getIt() thread safe and why?

public class X {
private long myVar;
public void setIt(long var){
myVar = var;
}
public long getIt() {
return myVar;
}
}

We all know that it is not thread safe as its possible that two concurrent threads may try to update and access the myVar at the same time. But an alternate answer i found was this

"It's not thread-safe because the instance variable is a 64-bit primitive. Read-only operations on instance-level primitives are atomic for 32-bit variables. But atomicity is not guaranteed for 64-bit variables because the JVM spec allows implementations to use two 32-bit read operations to access a 64-bit value. If a thread is in the process of reading the two 32-bit words of myVar, an interrupting thread could write to the high or low word of myVar before the first thread successfully reads both. This would result in a corrupt return value from getIt()."

Saturday, November 6, 2010

The Lock API

The Java 5.0 comes with new features in the concurrency package to take care of the locking strategy. The previous locking in Java 2.0 had a lot of disadvantages, like once a thread is waiting for a lock its not possible to interrupt it. Also the thread will wait for ever if its not able to acquire the lock. The order of acquiring the lock is also dependent on the thread scheduler and there is no way we can force the scheduler to give a prticular thread more priority in acquiring a lock. Intrinsic lock also needs to be released in the same block in which it acquires the lock.

All the above problems has been answered in the updates in Java 5.0 with the advent of the Lock package. We can acquire a lock equivalent to a synchronized block by using the lock() method in the ReentrantLock class. The example of Blocking Queue with wait() notify() can be rewritten with the lock strategy.

public class BlockingQueue5 extends BlockingQueue {
 
   private Queue queue = new LinkedList();
     String testingwait = new String();
     Lock lock = new ReentrantLock();
     Condition notFull = lock.newCondition();
     Condition notEmpty = lock.newCondition();
     private int capacity;

     public BlockingQueue5(int capacity) {
      super(capacity);
         this.capacity = capacity;
     }

     public void put(T element) throws InterruptedException {
      lock.lock();
         try {
    while(queue.size() == capacity) {
     
     notFull.await();
        
    }
    
    queue.add(element);
    notEmpty.signal();
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }finally{
    lock.unlock();
   }
     }

     public T take() throws InterruptedException {
      lock.lock();
         try {
    while(queue.isEmpty()) {
     
        notEmpty.await();
        
    }
    
    T item = queue.remove();
    notFull.signal();
    return item;
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }finally{
    lock.unlock();
   }
   return null;
     }

}

As can be seen the synchronized has been replaced by the lock(). Before any task is started the lock should be acquired . Its also imperative that the lock should be released come what may, so its essential that the release section should be in a  finally block. The wait and notify has been replaced by the Condition object. The await () and the signal()  methods  are equivalent to wait and notify. It necessary that the condition on which the await has been called , the signal is also called on the same condition.

Another method in the Lock class is the tryLock(). It solves the problems of deadlocking as seen in Dead Lock situation. The tryLock also comes with a overloaded method which takes in nanoseconds as parameters       which means the number of nano secs it will wait to acquire a lock after which it can resume with other operations. The tryLock acquires the lock if no other thread is waiting on that lock and in a thread ordering situation it gets the first preference. The  TransactionTryLock class below replaces the Transaction class and shows how tryLock can avoid deadlock situation.
public class TransactionTryLock extends Transaction{
 
 
private Lock accountA = new ReentrantLock();
private Lock accountB = new ReentrantLock();

public void transferA2B(){
 if(accountA.tryLock()) {
  System.out.println("lock for A held in A2B");
  try {
   // sleep given to force deadlock
   Thread.sleep(1000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
  if(accountB.tryLock()) {
   System.out.println("lock for B held in A2B");
   
  }

 }
}

public void transferB2A(){
 if(accountB.tryLock()) {
  System.out.println("lock for B held in B2A");
  try {
   // sleep given to force deadlock
   Thread.sleep(1000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  if(accountA.tryLock()) {
   
   System.out.println("lock for A held in B2A");
   
  }

 }
}

}

Friday, November 5, 2010

Simulating a ordering deadlock

One of the major drawbacks of the synchronized keyword is the deadlock scenario. If we need to acquire locks on two objects Object A and Object B simultaneously and then work on them , we need to make sure that the order of acquiring the lock is maintained. If the Lock on Object A is acquired first and then on B then the code can be considered safe and deadlock resistant. If on the other hand the order is not guaranteed then code has the potential of reaching a dead lock, as the following code demonstrates. The Transaction class has two methods transferA2B and transferB2A where the lock is acquired in two different orders. A sleep time of 1 sec is set after acquiring the lock in the first object in each method.

Transaction class


public class Transaction {
private Object accountA = new Object();
private Object accountB = new Object();
public void transferA2B(){
synchronized (accountA) {
System.out.println("lock for A held in A2B");
try { // sleep given to force deadlock
Thread.sleep(1000);
} catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace();
}
synchronized (accountB) {
System.out.println("lock for B held in A2B");
}
}
}

public void transferB2A(){
synchronized (accountB) {
System.out.println("lock for B held in B2A");
try { // sleep given to force deadlock
Thread.sleep(1000);
} catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace();
} synchronized (accountA) {
System.out.println("lock for A held in B2A");
}
}
}
}

Two Threads A and B will call the individual methods of Transaction from the run method, so I am avoiding the code snippets for the threads

The DeadloackTest class


public class DeadlockTest {
public static void main(String[] args) {
Transaction tran = new Transaction();
Thread a = new Thread(new ThreadA(tran));
  Thread b = new Thread(new ThreadB(tran));  
a.start();  b.start(); 
}}

Thread Communication using wait() notify()

The following is a very simple example to demonstrate how multiple threads can communicate using the wait() notify () paradigms. The idea is to design a bounded Blocking Queue having a max size of 5. There will be two threads using the queue, where a thread will put 10 messages into the queue whereas the other will read the 10 messages. If the Queue has reached max size the Publisher thread has to wait till the queue has been read by the Consumer Thread. Similarly the Consumer thread will wait if the Queue is empty

BlockingQueue

public class BlockingQueue {

private Queue queue = new LinkedList();
String testingwait = new String();
private int capacity;

public BlockingQueue(int capacity) {
this.capacity = capacity;
}

public synchronized void put(T element) throws InterruptedException {
while(queue.size() == capacity) {
wait();
}

queue.add(element);
notifyAll();
}

public synchronized T take() throws InterruptedException {
while(queue.isEmpty()) {
wait();

}

T item = queue.remove();
notify();
return item;
}
}

MyThread


public class MyThread extends Thread {

BlockingQueue queue = null;
String threadname = null;


public MyThread(String threadname,BlockingQueue queue) {
super(threadname);
// TODO Auto-generated constructor stub
this.queue = queue;
this.threadname = threadname;
}



public void run() {
if(threadname.equals("PUTTINGTHREAD")){
for (int i = 0; i < 10; i++) {
try {
queue.put("value"+i);

} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}else{
for (int i = 0; i < 10; i++) {
try {
queue.take();

} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}



}

}





The Executable Class


public class TestThread {

public static void main(String[] args) {
BlockingQueue queue = new BlockingQueue(5);
Thread t = new MyThread("PUTTINGTHREAD",queue);
Thread t1 = new MyThread("TAKINGTHREAD",queue);
t.start();
t1.start();

}
}

Sunday, October 31, 2010

Atomicity

What happens when we add one element of state to what was a stateless object? Suppose we want to add a "hit counter" that measures the number of requests processed. The obvious approach is to add a long field to the servlet and increment it on each request.

public class UnsafeCountingFactorizer implements Servlet {

private long count = 0;

public long getCount() {

return count;

}

public void service(ServletRequest req, ServletResponse resp) {

BigInteger i = extractFromRequest(req);

BigInteger[] factors = factor(i);

++count;

encodeIntoResponse(resp, factors);

}

}

Unfortunately, UnsafeCountingFactorizer is not thread-safe, even though  it would work just fine in a single-threaded environment. It is susceptible to lost updates. While the increment operation,  ++count, may look like a single action because of its compact syntax,  it is not atomic. shows what can happen if two threads try to increment a counter simultaneously  without synchronization. If the counter is initially 9, with some unlucky timing  each thread could read the value, see that it is 9, add one to it, and each set  the counter to 10. This is clearly not what is supposed to happen; an increment  got lost along the way, and the hit counter is now permanently off by one. This is known is Race Condition.

UnsafeCountingFactorizer has several race conditions that make its results unreliable. A race condition occurs when the correctness of a computation depends on the relative timing or interleaving of multiple threads by the runtime; in other words, when getting the right answer relies on lucky timing.

Race Condition can be avoided by lazy initialization

public class LazyInitRace {

private ExpensiveObject instance = null;

public ExpensiveObject getInstance() {

if (instance ==null){

instance = new ExpensiveObject();

}

return instance;

}

}

LazyInitRace has race conditions that can undermine its correctness. Say that threads A and B execute getInstance at the same time. A sees that instance is null, and instantiates a new ExpensiveObject. B also checks if instance is null. Whether instance is null at this point depends unpredictably on timing, including the vagaries of scheduling and how long A takes to instantiate the ExpensiveObject and set the instance field. If instance is null when B examines it, the two callers to getInstance may receive two different results, even though getInstance is always supposed to return the same instance.

If the increment operation in UnsafeSequence were atomic, the race conditioncould not occur, and each execution of the increment operation would have the desired effect of incrementing the counter by exactly one. To ensure thread safety, check-then-act operations (like lazy initialization) and read-modify-write operations (like increment) must always be atomic. Atomic state can be created by the syncronization or the free atomic package in new Java 1.5

public class CountingFactorizer implements Servlet { 
    private final AtomicLong count = new AtomicLong(0); 
     public long getCount() {
       return count.get(); 
     } 
 public void service(ServletRequest req, ServletResponse resp) {                                
         BigInteger i = extractFromRequest(req);    
         BigInteger[] factors = factor(i);
         count.incrementAndGet();
         encodeIntoResponse(resp, factors);
     }
 } 


The java.util.concurrent.atomic package contains atomic variable classes for effecting atomic state transitions on numbers and object references. By replacing the long counter with an AtomicLong, we ensure that all actions that access the counter state are atomic. Because the state of the servlet is the state of the counter and the counter is thread-safe, our servlet is once again thread-safe.We were able to add a counter to our factoring servlet and maintain thread safety by using an existing thread-safe class to manage the counter state, AtomicLong. When a single element of state is added to a stateless class, the resulting class will be thread-safe if the state is entirely managed by a thread-safe object. But, as we'll see in the next section, going from one state variable to more than one is not necessarily as simple as going from zero to one.

Where practical, use existing thread-safe objects, like AtomicLong, to manage your class's state. It is simpler to reason about the possible states and state transitions for existing thread-safe objects than it is for arbitrary state variables, and this makes it easier to maintain and verify thread safety.