Java Synchronization- part 1
By: Sachintha Hewawasam
Tags: First Post, Multithreading, Java, Programming, Synchronization

Before going to synchronization, I’ll explain about the multiple threads using a simple code.

image 1

The First-class is going to be the class “Countdown” while the class, “ThreadColor” with the color trick, will look like this.

public class ThreadColor {

public static final

public static final String ANSI_RED = "\u001B[31m";

public static final String ANSI_GREEN = "\u001B[32m";

public static final String ANSI_YELLOW = "\u001b[33m";

public static final String ANSI_BLUE = "\u001B[34m";

public static final String ANSI_PURPLE = "\u001B[35m";

public static final String ANSI_CYAN = "\u001B[36m";

public static final String ANSI_WHITE = "\u001b[37m";

}

image 2

Here… I have created the second class which extends thread.

image 3

Head to the main method, since we have created 2 classes, and then starting two threads.

From switch statement (image 1) that we have got from one thread named “Thread 1” which will print text in cyan and the 2nd thread which will print text in purple.

Here… now let's see what's happening.

image 4

Here you can see, thread 1 in CYAN while thread 2 is in PURPLE. But we can not predict how the result would be, ie. the order of the two colors. You can see that when we run the code a few times, it will give us completely different logs.

Now, we are going to add the instance variable, “Private int I;” that changes the local variable “I” to an instance variable. Let’s look at the new result.

image 5

Now we can notice, the result is different this time. Instead od=f each thread counting down to 10, the numbers seem to be sort of duplicated.

Why??

As you can see, number 10 is duplicated. Not only 10, you can see a few other numbers too have been duplicated. The only thing we did was changing the local variable to an instance variable as follows:

class Countdown {

private int i;

Heap : this the memory of the application that is shared by all the threads and each thread has a Thread Stack. That is the memory, which is unique to each thread. Simply speaking, any thread can’t access to another thread’s stack. But the threads can access the Heap. The local variable is stored in Thread stack, that is each thread has its own copy of the local variable. Whereas, the instance variables are stored in Heap. So when multiple threads are working together with the same object, they are likely to share the same object. In that case, if one thread changes the value, another thread will take the new value that was changed by the first thread. Similarly, when “i” was acting as the local variable, threads had their own version of “i”. Once we changed “i” as an instance variable, the 2 threads had to access this shared resource which is stored in the Heap. That’s why each thread seem to skip some numbers.

for statement

It decrements I and checks for the condition i>0; the idea behind the “for statement” is, it consist of several steps such as decrementing, checking etc. Therefor the thread can be suspended in between the step. It can be suspended after decrementing “i”, before checking the condition or immediately after executing all the codes and then the printing. Decrementing “i”, checking the condition & printing out the values: these 3 steps can make the current thread , to be suspended. As you can understand, in the first attempt, both the threads considered the value of “i”as 10, so the thread 1 prints 9 but the thread 2 prints 8. While thread 1 was executing the for statement, thread 2 must have been without surpassing thread 1. Therefore it takes the value of “i” as 9 and execute the for block and prints 8. I think this explanation gives you an idea about this.

When accessing the same resources, we have to go through this situation and it is called “Thread interference” . it is also referred as “Race condition”. Always keep in mind that this is a serious issue when it comes to writing or updating the same resource.

We can do this without skipping numbers or avoiding the interference, ie. pass the same Countdown object to both the threads.

public class Main {



public static void main(String[] args) {

Countdown countdown1 = new Countdown();

Countdown countdown2 = new Countdown();



CountdownThread t1 = new CountdownThread(countdown1);

t1.setName("Thread 1");

CountdownThread t2 = new CountdownThread(countdown2);

t2.setName("Thread 2");



t1.start();

t2.start();

}

}

Take a look at the above instance, where there are two new objects for the threads, not sharing the Heap. Check the results, you don’t see any interference! Each thread Counts down from 10 to 1 successfully.

image 6

The real question is, will this be applicable in Real-world? Will this work for a bank account, where someone deposits money in your account while you are withdrawing some money from the ATM? Therefore it appears that we have to use the same object in order to maintain the integrity of the data. Because this is the only way that lets us know the exact bank balance after executing several threads (transactions), right? There can be several threads that are waiting to change the bank balance, simultaneously. So we need to allow multiple threads to change it while preventing the “Race condition”.