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

Friday, August 20, 2010

Thread-safe Generic Class in Java

Assuming that you are a Java Developer, I can say that you have at some point or the other must have used Generics in your code, be it using a Generic Collection (if you have worked with Java5+) or in any other way. Even if you are not a Java developer, you must have played with Templates (in C++) in your school/college days.

Today, we are going to do something similar in Java. We are going to create a Generic Stack class in Java, which you can use to create a Stack of Integers, Floating Point Numbers, or a Stack of Students or any custom type that you have. Just to make code a bit more interesting and tough, I have also made it thread-safe so that multiple threads can use this stack without leaving it in an inconsistent state.

public class GenericStack<T> {

private List<T> items;
private int top;
private int size;
private static final int INIT_SIZE = 100;

public GenericStack(){
size = INIT_SIZE;
items = new ArrayList<T>(INIT_SIZE);
top = -1;
}

public GenericStack(int size){
this.size = size;
items = new ArrayList<T>(size);
top = -1;
}

private boolean isEmpty(){
return (top==-1);
}

private boolean isFull(){
return (top == size-1);
}

// Push an Item in Stack
public void push(T item){
synchronized(items){
// While stack is Full
while(isFull()){
try{
// Wait till Stack is Full
items.wait();
}
catch(InterruptedException e){
e.printStackTrace();
}
}
// Produce Item
items.add(++top, item);
// Notify other threads
items.notify();
}
}

// Pop an item out of stack
public T pop(){
T item = null;
synchronized(items){
// While Stack is Empty
while(isEmpty()){
try{
// Wait if its empty
items.wait();
}
catch(InterruptedException e){
e.printStackTrace();
}
}
// Consume an item
item = items.get(top--);
// Notify other threads
items.notify();
}
return item;
}
}

Most of the above code is self-explanatory but lets highlight some of the major concepts used here:
  • To create a Generic class, one must specify the Type along with the class name (as done using T).
  • When you initialize it, all the occurrences of T will be replaced by that particular type.
  • We have also made the above Stack class thread-safe, i.e. it can be shared and updated by multiple threads in a consistent manner using synchronized blocks.
  • We have checked before pushing for a Full Stack and we also check for an Empty Stack before popping an element
  • We have not made the isFull() and isEmpty() methods as synchronized as they are private (hence not visible to clients) and are always called from an synchronized context from within the class.
  • If you need isFull() and isEmpty() to be public then make them also synchronized to make them thread-safe
  • It is always better to have synchronized blocks rather than synchronized methods as it is always better to synchronize as less code as possible. Although, here we could not make much use of this concept but rather than obtaining the lock on the calling object, we obtain a lock on the shared list of items.
  • Calling synchronized(items) means if some other thread has not yet acquired a lock on items (By the way, each Object in Java has an associated Lock with it), then this current thread acquires the associated lock and proceeds. Otherwise if some other thread has currently acquired the synchronized block, then it must wait in the wait list of the object (items) in question. The thread then waits until it receives a notification that the lock has become available for acquisition and then it competes with other waiting threads to acquire the lock.
  • Calling items.wait() results in the current thread being placed in the wait list of items after releasing the lock. You can only call object.wait() after you have acquired the lock on the object.
  • Calling items.notify() results in sending the notification to one of the threads in the wait pool of threads which can then compete for the lock.
  • Note that items.notify() does NOT releases the lock. Only exiting the synchronized block/method releases the lock that was acquired when the thread entered the synchronized block/method.

You can easily create two or more threads (viz. Producer and Consumer) and pass them the same Stack and play with them to randomly create and consume data and check that you Stack class is indeed thread-safe.

Generic Methods

Talking more about generics, you can also make a method accept Generic parameters without the enclosing class declaring the Generic type as done in the following example:

public <T> List<T> createArrayList(T t){
List<T> arr = new ArrayList<T>();
return arr;
}

This weird looking syntax has a meaning:

  • This method basically lets you create an arraylist of any type, type is passed to it as an argument.
  • Since you are not defining the type at Class-level, then there must be a place where you should define the type of your method and distinguish it from other non-generic methods for the compiler.
  • So, we declare the type <T> immediately after public modifier to say that we use a Generic Type T in this method, which like others will be replaced at runtime with any real type. (just like in case of Generic classes)
  • We call this method passing to it a valid reference to any Object of any type (Integer, Float, or you own custom class Student). For example, we can do:
Integer i = 23;
List<Integer> intList = createList(i);

or

Student st = new Student();
// Do anything with st here
List<Student> students = createList(st);

Ok, I agree this is not one of really useful examples for showcasing the power of a generic method but I hope that the intent is clear and so is the syntax. As always, your valuable comments are welcome and desired. Any corrections must also found place in comments. Sayonara :-)

Wednesday, March 24, 2010

Singletons, Threads & Double Checked Locking

This blog entry extends on the first entry I wrote about Singletons. Today I try to explain the usage of Singletons in a multi-threaded environment.

A typical Singleton would look like the following:

MySingletonJava

This Singleton class would work perfectly fine in a single-threaded environment. But, how many Java based applications that you have worked on, are single-threaded? None, perhaps.

Can you see what’s terribly wrong with it when your application has multiple threads running simultaneously ??

Well, the answer lies in the way the instance is lazy initialized. The null-checking and initializing the instance need to be an atomic operation. Lets see what would happen if following sequence of events happen:

  • Thead A calls getInstance() for the first time. And checks whether instance is null or not. It finds it true and goes to execute line 11.
  • At this point, it is pre-empted by another thread: Thread B, which also calls getInstance(), checks for the instance null check, since it is not yet initialized, the private constructor is called and instance is now initialized with a state.
  • Thread A resumes control back and starts from where it left i.e line 11. Now the real problem occurs. Since it checked for the null-check on line 10 when it last run and found it to be true, so when it resumes execution, it will execute from line 11 and again initialize the instance and hence two objects would be created and the whole point of having a single object is violated.

Thus, we really need to do something about the situation. No problems, Synchronization comes to the rescue. Most of us (naive programmers) would tend to get rid of this problem by writing code like below:

MySynchronizedSingletonJava

The only change that occurs here is that we have made our static factory as synchronized method, which makes sure that no possible combination of interleaving of threads could create two objects like it did in the previous case. Although, this works fine but on close inspection, we find that synchronization is necessary only for the first time, and not needed later on (since instance will always be non-null later on) And synchronizing the whole method is thus uncalled for and pretty expensive. We must think of other ways of accomplishing this.

1. Do Not Lazy Initialize

If we do NOT need lazy initialization of the resource, then a perfect method to do away with synchronization would be:

Singleton1Java

Using this, we depend on the JVM’s capability to execute the static block as soon as the class is loaded first (when it is accessed or referred in code).

Thus, the VM makes sure that the instance is well initialized, before any thread tries to call getInstance() method. And since static blocks are executed only once, so no chance of creating more objects. One scenario that I could fail this approach is when this class is loaded again (perhaps by a different classloader in a different namespace)

Another way to write the above code would be:

Singleton2Java

However, I prefer the first way (with static blocks) that gives us more flexibility by allowing us to write a block of code instead of just calling the constructor.

2. Use Double Checked Locking

A very common, popular and misunderstood programming idiom that looks like the following and works with Java 1.5 and above only.

Singleton3Java

See how cleverly, we have limited the scope of synchronization here. The synchronization occurs only for the first time (when the instance is null), after that the synchronization never occurs as the instance is not null. This is what we needed. But you must make this variable as volatile to work it correctly (due to Java Memory Model implementation)

To better understand this programming idiom, I would suggest reading this and this.

I think its enough for one blog post. Any code corrections, new ideas and comments are welcome.