Saturday, January 30, 2010

Concurrent Programming Concepts

Introduction
Writing linear programs, while being a lot easier than concurrent programming, is a thing of the past. Linear programming was effective while Moore's Law held; however, as raw processing speed has currently hit a brick wall we have had to look at executing code in parallel. With more and more systems being built with multiple processors with multiple cores each, not taking advantage of them is poor programming. This limits the scalability, responsiveness, and performance of any program. To make things worse, many that code using Java still operate linearly even though threads permeate Java's system. Servlets operate using threads and can be concurrently accessed by multiple requests from users, GUI frameworks use threads underneath to retain responsiveness, the garbage collector operates in separate threads of it own, and etc. They are everywhere. If a program is being created without concurrency in mind, you run the great risk of inadvertently creating errant code because even if you yourself don't use multiple threads, that doesn't mean there aren't any there to access it. If there are multiple threads accessing the same mutable (changeable) variables, and those variables aren't properly synchronized, your program is broken. End of story. It may look like your code works initially, and it may work correctly for years to come, but it all amounts to lucky/unlucky timing. The worst time to see that the code is broken is when it fails in production under heavy load (and no doubt that is when it will happen because of the system having so much going on).

State
Concurrent programming is not defined by using threads and locks; rather, it is all about maintaining state. Threads and locks are the building blocks that we use to maintain state with concurrent access. An object's state is encompassed by the instance variables, static variables, or other dependent objects. When we talk about thread-safety, it may sound like we are talking about code, but what we are really saying is that we are trying to protect data by controlling concurrent access to the data.

Ways to Manage It
There are three primary ways in Java to maintain a class's state:

  1. Don't share state across threads (encapsulation).

  2. Make state variables immutable (unchangeable).

  3. Use synchronization techniques whenever accessing state variables.


It is important to remember to encapsulate synchronization inside an object so that when anything uses it, it doesn't have to worry about implementing its own synchronization outside of the object for the object. Stateless objects are always thread-safe, because there is nothing it has to remember or keep track of during its execution. If a single element of state is added to a stateless class, then it will be thread-safe if and only if the state is fully managed by a thread-safe object. When there are multiple variables that comprise an object's state, it is important to know which ones are dependent upon each other, and which ones that aren't. If there are 2 or more variables that are related in some fashion are accessed by more than one thread could result in the 2 variables getting out of sync (meaning the data contained within them doesn't match up). If the variables are independent of each other, the synchronization may be exclusive to each variable. This means that each one can be read, modified, or written to without worrying what the others are.

Final Thought
Concurrent programming is difficult at first, but it also not going away... ever. The only way to get better at is to read about it, read it again, and do it until my head and fingers hurt. Repetition is the mother of knowledge. That is the only way this will get any easier.

Thursday, January 28, 2010

Interrupting Thread Execution

In one of my programming classes, we had to write a multi-threaded chat server that could accept an arbitrary number of clients and transmit messages from one to another. We knew little about concurrency at the time, so we didn't know how to stop a thread from executing. Because we were young and aspiring students that were motivated to get a project done by a certain deadline, we went where we always go when looking for an answer... Google (and the professor)! This is basically what we found from many different sites, forums, and blog posts (I think my professor agreed/told us to do it this way too):

http://www.roseindia.net/javatutorials/shutting_down_threads_cleanly.shtml

While this will work, this is not the proper or best way to stop a thread and can cause problems with responsiveness, liveness, deadlocks, etc as we will see in later posts. So here is the general idea of the bad example:
package org.tiki.threadexamples;


public class BadThreadStopExample extends Thread {

private boolean continueRunning = true;

public void run() {

while ( continueRunning ) {

// Do stuff
System.out.println( "Bad thread is doing its thing." );
}
}

public void cancel() {

continueRunning = false;
}

public static void main( String[] args ) {

BadThreadStopExample thread = new BadThreadStopExample();
thread.start();

// Do stuff

thread.cancel();
}
}
So what is the correct way of handling these things? I'm glad you asked. I've recently been reading the book Java Concurrency in Practice by Brian Goetz and I highly recommend it. After reading a few chapters, it boggles my mind as to why there are so many examples on the internet that follow the above paradigm. I am guilty of writing similar code in most of my multithreaded programs, so if you've done this, you're not alone. I have been enlightened on how this should be written (thank you Brian Goetz)... the thread interruption methods!

  • public void interrupt()

  • public boolean isInterrupted()

  • public static boolean interrupted()

Using these methods, we can change the above code into this:
package org.tiki.threadexamples;


public class GoodThreadStopExample extends Thread {

public void run() {

while ( !Thread.currentThread().isInterrupted() ) {

// Do stuff
System.out.println( "Good thread is doing its thing." );
}
}

public void cancel() {

interrupt();
}

public static void main( String[] args ) {

GoodThreadStopExample thread = new GoodThreadStopExample();
thread.start();

// Do stuff

thread.cancel();
}
}
So this code now sends an interrupt message to the thread, and the while loop now checks that message instead of defining your own variable. However, if blocking functions are in the loop, such as serverSocket.accept() or in.readLine(), the thread may not behave as you think it would. Interrupt methods don't always cause blocking functions to stop what they are doing. How to handle these cases is a bit different and what you do to handle them can depend on the situation and the requirements of the program... So that is for another post.