Tuesday, 3 April 2012

Java Threads


This post is the first of set of posts about Java Concurrency.
The concurrency is the fact to made several things at the same time using several threads.
A thread, also called Lightweight Process, is treatment unity. Threads executes code in parralel of each other threads currently running. When you’ve only one processor, there is a thread running at the same time of the others, you only have the impression of concurrency (I don’t say it’s not useful, I say it’s different), but when you’ve multiple processors, you’ll see the power of multi threading. In this case, you can have your threads distributed on the processors of the computer.
In Java, a thread is an instance of the class java.lang.Thread. A Thread can be managed in one of these two ways :
  1. Directly mapped to a native thread of the operating system. This is used when the operating system provide a preemptive threading system.
  2. Managed by the virtual machine in a premptive way.
A preemptive system, is a system in which the threads are managed by a scheduler and can be interrupted at any time to give processor to an other thread. When you program, you doesn’t have to pay attention of which type of threads you use, the result will normally be the same. But you’ve to know that there can differences between operating systems.
There is three very important concepts when doing concurrent programming :
  1. Atomicity : An operation is said atomic when it cannot be interrupted. There is almost no atomic operations in Java, the only we’ve is the assignation a = 5, but a = b++ is not atomic. In some cases, you’ll have to make atomic some actions with synchronization, we’ll see later how to do that.
  2. Visibility : This occurs when a thread must watch the actions of an other threads by example the termination of the thread. This also implies some kind of synchronization.
  3. Order of execution : When you have normal program, all you lines of code run in the same order every time you launch the application. This is not the case when you make concurrent programming. You first instruction can followed by an instruction of the thread B ou by the first instruction. And that can change every time you launch the application. The order of execution is not guaranteed ! I will certainly repeat that sometimes, but that’s important to know.
We’ll see these concepts more deeply in the others parts of the set.
Lets start introducing the Thread class in Java. You can create threads in two ways :
  1. Extends Thread
  2. Implements Runnable and pass an instance of your news class to the Thread constructor
The first solution isn’t a good solution because what you’re creating is not a new specialized thread, but severals instructions to run in a new Thread, namely a Runnable. Implementing Runnable is also better because Runnable is an interface and so, you can also extends a class and implementing Runnable, that’s useful in some cases.
In my examples, I’ll always use the first way. So let’s declare our first Runnable :
public class MyFirstRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("In a thread");
    }
}
And use it to create a new Thread and start it :
Thread thread = new Thread(new MyFirstRunnable());
thread.start();
The Thread will stopped when the end of the run() will be reached. You cannot force a thread to stop (there is stop() method, but deprecated), we’ll see later how to properly stop a thread.
And now, what happens if we add a simple line of code to our program :
Thread thread = new Thread(new MyFirstRunnable());
thread.start();
System.out.println("In the main Thread");
Can you predict the result of this code ? Nobody can’t, it’s not predictable, you can have :
In a thread
In the main Thread
or
In the main Thread
In a thread
And we cannot do better than that.
You can use the Runnable several times :
Runnable runnable = new MyFirstRunnable();
 
for(int i = 0; i < 25; i++){
    new Thread(runnable).start();
}
Now, 25 threads are launched.
You can also give names to Thread using the setName() method. You can get the name of the current thread using Thread.currentThread().getName(). Let’s do a little example :
public class MySecondRunnable implements Runnable{
    @Override
    public void run() {
        System.out.printf("I'm running in thread %s \n", Thread.currentThread().getName());
    }
}
Runnable runnable = new MySecondRunnable();
 
for(int i = 0; i < 25; i++){
    Thread thread = new Thread(runnable);
    thread.setName("Thread " + i);
    thread.start();
}
This is the best example to see that the other is unpredictable. Here are two executions on my machine :
1.
I'm running in thread Thread 0
I'm running in thread Thread 1
I'm running in thread Thread 2
I'm running in thread Thread 3
I'm running in thread Thread 4
I'm running in thread Thread 5
I'm running in thread Thread 7
I'm running in thread Thread 14
I'm running in thread Thread 13
I'm running in thread Thread 12
I'm running in thread Thread 11
I'm running in thread Thread 10
I'm running in thread Thread 9
I'm running in thread Thread 8
I'm running in thread Thread 6
I'm running in thread Thread 15
I'm running in thread Thread 16
I'm running in thread Thread 17
I'm running in thread Thread 18
I'm running in thread Thread 19
I'm running in thread Thread 20
I'm running in thread Thread 21
I'm running in thread Thread 22
I'm running in thread Thread 23
I'm running in thread Thread 24
2.
I'm running in thread Thread 0
I'm running in thread Thread 1
I'm running in thread Thread 2
I'm running in thread Thread 3
I'm running in thread Thread 4
I'm running in thread Thread 5
I'm running in thread Thread 6
I'm running in thread Thread 7
I'm running in thread Thread 8
I'm running in thread Thread 9
I'm running in thread Thread 10
I'm running in thread Thread 11
I'm running in thread Thread 12
I'm running in thread Thread 13
I'm running in thread Thread 14
I'm running in thread Thread 15
I'm running in thread Thread 16
I'm running in thread Thread 17
I'm running in thread Thread 18
I'm running in thread Thread 19
I'm running in thread Thread 20
I'm running in thread Thread 21
I'm running in thread Thread 22
I'm running in thread Thread 23
I'm running in thread Thread 24
Like you can see, the order the threads instructions are executed is not guaranteed at all.
So here we are with the first part of this suite of articles about Java Concurrency. In the next post, we’ll see the operations you can make directly on threads (stopping, joining, sleeping, …).
I hope you found that post interesting.


we’ll see in this article what we can do to manipulate Threads.
When we’ve Threads, we can make several operations on the Threads :
  • Make the current Thread sleeping during x milliseconds
  • Wait for an other thread to complete
  • Manage the priorities of Threads and pause a thread to give an other thread the opportunity to run
  • Interrupt a thread
We’ll now see how to do all these things.
First and easier, we can make a thread sleeping for a certain number of milliseconds. To do that, the Thread class has a method sleep(long millis). But this method is static, so you can only make the current Thread sleeping. You cannot choose the thread you want to make sleeping, your only choice is the current Thread so :
Thread.sleep(1000);
makes the current Thread sleep during 1000 milliseconds (1 second). But, you have to catch an exception, InterruptedException. This exception occurs if the sleeping thread is interrupted. So you have to do that :
try {
 Thread.sleep(1000);
} catch (InterruptedException e){
 e.printStackTrace();
}
But this not the good way to manage the InterruptedException. We’ll see in one moment, how to deal with this exception.
If you want more precision, you can use the overloaded version of sleep that takes the number of millis plus a certain number of nanos to sleep. The precision of this sleep depends on the system timers and clocks.
For example, if you want to sleep 1000 milliseconds and 1000 nanoseconds (1 microsecond), you can do like that :
try {
 Thread.sleep(1000, 1000);
} catch (InterruptedException e){
 e.printStackTrace();
}
Here is a little example to test that :
public class SleepThread {
    public static void main(String[] args) {
        System.out.println("Current time millis : " + System.currentTimeMillis());
 
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
        System.out.println("Current time millis : " + System.currentTimeMillis());
 
        System.out.println("Nano time : " + System.nanoTime());
 
        try {
            Thread.sleep(2, 5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
        System.out.println("Nano time : " + System.nanoTime());
    }
}
In my computer, this produce this result :
Current time millis : 1273959308480
Current time millis : 1273959309480
Nano time : 5878165216075
Nano time : 5878166730976
You can see that the sleep of millis is very precise, but with nanos the result can vary a lot. And of course, the result depends of your computer, your operating system and your configuration.
An other thing, you can do with Threads, is waiting for an other thread to die. For example, you can create five thread to compute sub result and wait for these 5 threads to finish to compute the final results based on the results of the five threads. To do that, you can use the join() method of the Thread class. This method is not static, so you can use it on any thread to wait for it to die. Like sleep() this method throws InterruptedException in the when the thread is interrupted during waiting for an other thread. So to wait on thread2, you just have to do that :
try {
 thread2.join();
} catch (InterruptedException e){
 e.printStackTrace();
}
That will make the current Thread waiting for thread2 to die. You can also add a timeout in millis, or millis + nanos, with the overloaded versions of join(), join(long millis) and join(long millis, int nanos). Here is little example that shows all that stuff :
public class JoinThread {
 public static void main(String[] args) {
  Thread thread2 = new Thread(new WaitRunnable());
  Thread thread3 = new Thread(new WaitRunnable());
 
  System.out.println("Current time millis : " + System.currentTimeMillis());
 
  thread2.start();
 
  try {
   thread2.join();
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 
  System.out.println("Current time millis : " + System.currentTimeMillis());
 
  thread3.start();
 
  try {
   thread3.join(1000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 
  System.out.println("Current time millis : " + System.currentTimeMillis());
 }
 
 private static class WaitRunnable implements Runnable {
  @Override
  public void run() {
   try {
    Thread.sleep(5000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
}
That produce this result on my computer :
Current time millis : 1274015478535
Current time millis : 1274015483538
Current time millis : 1274015484538
You can see that the first join() wait 5 seconds for the other thread and when we set a timeout, we wait only 1 seconds and return from join method.
When working with Threads, it’s also possible to change the priority of a Thread. In the Java Virtual Machine, the Thread scheduler, use a priority-based scheduling. So if a Thread enter in Runnable state with a higher priority than the running Thread, the new Thread will run and the current running thread will return to Runnable state and waits for its turn. But this behaviour is not guaranteed and is completely depending on the virtual machine you are working on. So, do not rely on thread priorities, just use them to improve efficiency of your program.
Normally, the priority range of Threads is an integer from 0 to 10, but some virtual machine have lower or higher ranges. To know the range of priority, you can use constants of the Thread class :
public class ThreadPriorityRange {
 public static void main(String[] args) {
  System.out.println("Minimal priority : " + Thread.MIN_PRIORITY);
  System.out.println("Maximal priority : " + Thread.MAX_PRIORITY);
  System.out.println("Norm priority : " + Thread.NORM_PRIORITY);
 }
}
On my computer, I’ve the most current values :
Minimal priority : 1
Maximal priority : 10
Norm priority : 5
To set the priority of a Thread, you can use the setPriority(int priority) method of the Thread class. If you enter a value greater than the maximal priority, the maximal value will be used. If you don’t specify a priority, the used priority, will be the priority of the current Thread.
An other way to works with priority is the yield() method. This method is static, so this works on the current Thread. The purpose of this method is to make the Thread going to Runnable again and to give the opportunity to other threads to get their turn. But in practice, the behaviour of this method is not guaranteed. It can be implemented as a no-op on certain systems. It’s not easy to test that in practice, because the results can truly depends on your computer, virtual machine and operating system. It’s a good things to not use the priorities of Threads in practice.
The last thing you can do with a Thread, is to interrupt it. In Java, you have no way to force a Thread to stop, if the Thread is not well-done, it can continue its execution infinitely. But you can interrupt a Thread with the interrupt() method. This method interrupt the thread, if the thread is sleeping or joining an other Thread, an InterruptedException is thrown. You have to know that if the thread was sleeping or joining, the interrupted status of the Thread will be cleared. Namely, the method isInterrupted() will return false. A little example to demonstrate that :
public class InterruptThread {
 public static void main(String[] args) {
  Thread thread1 = new Thread(new WaitRunnable());
 
  thread1.start();
 
  try {
   Thread.sleep(1000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 
  thread1.interrupt();
 }
 
 private static class WaitRunnable implements Runnable {
  @Override
  public void run() {
   System.out.println("Current time millis : " + System.currentTimeMillis());
 
   try {
    Thread.sleep(5000);
   } catch (InterruptedException e) {
    System.out.println("The thread has been interrupted");
    System.out.println("The thread is interrupted : " + Thread.currentThread().isInterrupted());
   }
 
   System.out.println("Current time millis : " + System.currentTimeMillis());
  }
 }
}
That produce that kind of result :
Current time millis : 1274017633151
The thread has been interrupted
The thread is interrupted : false
Current time millis : 1274017634151
You can see that after one second, the second thread is interrupted and that the interrupted status has been set to false. If you are not sleeping, but making a lot of heavy actions, you can test for interrupt like that to make your thread correctly interrupts :
public class InterruptableRunnable implements Runnable {
 @Override
 public void run() {
  while(!Thread.currentThread().isInterrupted()){
   //Heavy operation
  }
 }
}
Now that you know how to interrupt a thread, you can imagine, that simply catch the InterruptedException is not enough to make your thread “interrupt safe”. Imagine that your thread something like that :
public class UglyRunnable implements Runnable {
 @Override
 public void run() {
  while(!Thread.currentThread().isInterrupted()){
   //Heavy operation
   try {
    Thread.sleep(5000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   //Other operation
  }
 }
}
And now, an other thread want to interrupt your thread while your thread is sleeping. The sleep will be interrupted, but the interrupted status will be cleared so the loop will continue. A solution to make a better thread is to interrupt again the thread after an InterruptException :
public class BetterRunnable implements Runnable {
 @Override
 public void run() {
  while(!Thread.currentThread().isInterrupted()){
   //Heavy operation
   try {
    Thread.sleep(5000);
   } catch (InterruptedException e) {
    Thread.currentThread().interrupt();
   }
   //Other operation
  }
 }
}
With that code, the interrupted status will be restored and the loop will be stopped after interrupt. Depending on your code, you can also add a continue statement after the interrupt() to not make operations after interrupt. In some cases, you’ll also needs to make several if statements to test the interrupted status to do or not to do some operations.
So, we’ve now covered the main operations you can do on threads. I hope you found this article interesting.

After learning how to create threads and manipulate them, it’s time to go to most important things : synchronization.
Synchronization is a way to make some code thread safe. A code that can be accessed by multiple threads must be made thread safe. Thread Safe describe some code that can be called from multiple threads without corrupting the state of the object or simply doing the thing the code must do in right order.
For example, we can take this little class :
public class Example {
    private int value = 0;    
 
    public int getNextValue(){
        return value++;
    }
}
It’s really simple and works well with one thread, but absolutely not with multiple threads. An incrementation like this is not a simple action, but three actions :
  • Read the current value of “value”
  • Add one to the current value
  • Write that new value to “value”
Normally, if you have two threads invoking the getNextValue(), you can think that the first will get 1 and the next will get 2, but it is possible that the two threads get the value 1. Imagine this situation :
Thread 1 : read the value, get 0, add 1, so value = 1
Thread 2 : read the value, get 0, add 1, so value = 1
Thread 1 : write 1 to the field value and return 1
Thread 2 : write 1 to the field value and return 1
These situations come from what we call interleaving. Interleaving describe the possible situations of several threads executing some statements. Only for three operations and two threads, there is a lot of possible interleavings.
So we must made the operations atomic to works with multiple threads. In Java, the first way to make that is to use a lock. All Java objects contains an intrinsic locks, we’ll use that lock to make methods or statement atomic. When a thread has a lock, no other thread can acquire it and must wait for the first thread to release the lock. To acquire the lock, you have to use the synchronized keyword to automatically acquire and release a lock for a code. You can add the synchronized keyword to a method to acquire the lock before invoking the method and release it after the method execution. You can refactor the getNextValue() method using the synchronized keyword :
public class Example {
    private int value = 0;    
 
    public synchronized int getNextValue(){
        return value++;
    }
}
With that, you have the guarantee that only thread can execute the method at the same time. The used lock is the intrinsic lock of the instance. If the method is static, the used lock is the Class object of Example. If you have two methods with the synchronized keyword, only one method of the two will be executed at the same time because the same lock is used for the two methods. You can also write it using a synchronized block :
public class Example {
    private int value = 0;
 
    public int getNextValue() {
        synchronized (this) {
            return value++;
        }
    }
}
This is exactly the same as using the synchronized keyword on the method signature. Using synchronized blocks, you can choose the lock to block on. By example, if you don’t want to use the intrinsic lock of the current object but an other object, you can use an other object just as a lock :
public class Example {
    private int value = 0;
 
    private final Object lock = new Object();
 
    public int getNextValue() {
        synchronized (lock) {
            return value++;
        }
    }
}
The result is the same but has one difference, the lock is internal to the object so no other code can use the lock. With complex classes, it not rare to use several locks to provide thread safety on the class.
There is an other issue with multiple threads : the visibility of the variables. This seems when a change made by a thread is visible by an other thread. For performance improvements, the Java compiler and virtual machines can made some improvements using registers and cache. By default, you have no guarantee that a change made by a thread is visible to an other thread. To make a change visible to an other thread, you must use synchronized blocks to ensure visibility of the change. You must use synchronized blocks for the read and for the write of the shared values. You must make that for every read/write of a value shared between multiple threads.
You can also use the volatile keyword on the field to ensure the visibility of read/write between multiple threads. The volatile keyword ensure only visibility, not atomicity. The synchronized blocks ensure visibility and atomicity. So you can use the volatile keyword on fields that doesn’t need atomicity (if you make only read and write to the field without depending on the current value of the field by example).
You can also note that this simple example can be solved using AtomicInteger, but that will be covered later in an other part of the posts.
Pay attention that trying to solve thread safety on a problem can add new issues of deadlock. By example, if thread A owns the lock 1 and are waiting for the lock 2 and if lock 2 is acquired by thread B who waits on lock 1, there is a deadlock. Your program is dead. So you have to pay great attention to the locks.
There is several rules that we must keep in mind when using locks :
  1. Every mutable fields shared between multiple threads must be guarded with a lock or made volatile, if you only need visibility
  2. Synchronize only the operations that must synchronized, this improve the performances. But don’t synchronize too few operations. Try to keep the lock only for short operations.
  3. Always know which locks are acquired and when there are acquired and by which thread
  4. An immutable object is always thread safe
We continue with the Java Concurrency thema with the semaphores. Semaphores is also a way to synchronize threads.
Semaphores are a really simple concept, invented by the famous Dutch computer scientist Edsger Dijkstra. Basically a semaphore is a counter (integer) that allows a thread to get into a critical region if the value of the counter is greater than 0. If it’s the case, the counter is decremented by one otherwise, the thread is waiting until it can go. And when the thread go away from the critical region, the counter is incremented by one to allow one more thread to pass the critical region. A semaphore is created with a certain value for its counter. So, you can execute two actions on a semaphore P and V.
By example, if you have a critical that cannot be executed concurrently, you can use a semaphore :
sem mutex = new sem(1)
 
P(mutex)
//Critical region
V(mutex)
So you must always call by yourself the P operation before the critical region and V after it. We call a mutex (mutual exclusion) a semaphore with a value of one. So only one thread can enter the region guarded by the semaphore. This is the most used semaphore. The other use of semaphore is to guard a set of resources like database connections or a data pool.
In Java, a semaphore is created using the java.util.concurrent.Semaphore class. You can create easily :
Semaphore mutex = new Semaphore(1);
Semaphore available = new Semaphore(100);
The P and V operations are represented using the acquire and release methods. The method acquire can be interrupted if the thread is interrupted. There is an ininterruptible version with the method acquireUninterruptibly(). There is also a third version with the tryAcquire method. This method acquire a permit only if there is one permit available, otherwise, this method return false directly. All the waiting methods have also an overloaded version with a timeout. You can also acquire several permits at once using the permits argument to the different versions of acquire methods.
A little example with a mutex using the same example as the previous post on Java concurrency :
public class Example {
    private int value = 0;
 
    private final Semaphore mutex = new Semaphore(1)
 
    public int getNextValue() throws InterruptedException {
        try {
            mutex.acquire();
            return value++;
        } finally {
            mutex.release();
        }
    }
}
For more informations about Semaphore in Java, the best is to consult the Javadoc of the Semaphore class.
To conclude, semaphores are a powerful ways to solve concurrency problems, but this is not adapted to all problems. If you need only mutual exclusion, synchronized blocks are a better solutions. The problems with semaphores is that you can forget to call the release method and that can cause deadlock sometimes difficult to find.

No comments:

Post a Comment