Java thread essentials

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • sankar2011
    New Member
    • Nov 2011
    • 18

    Java thread essentials

    1> What is reordering of statements in a single thread.

    Ans. Compiler/JVM reorder the statements in a particular thread so that it does not affect the code semantics for single thread execution. For example see the following code.
    Code:
    class A{
    
        private int k = 0;
        private boolean l = false;
        public void example(int a, boolean b){
            k = a;//....  Line 1
            l = b;//....  Line 2
    
        }
    
        public void show(){
            System.out.println(k);//.... Line 3
            System.out.println(l);//.... Line 4
        }
    
        public static void main(String args[]){
    
            A a = new A();
            a.example(3,"true");
            a.show();
    
        }
    }
    Scenario 1: Here the order of Line 1 and Line 2 to execute is not at all important. Because they do not depend on one another. So they may be reordered. Now it is very normal that in the main thread the order of execution of the lines are 2,1,3,4.
    So output will be
    3
    true

    But the order of execution in the method show() can never be reordered. Because that will change the method semantics. Then the result would be as below
    true
    3
    But this was not the intent of the program. So this would never happen.

    Scenario 2: But scenario may be different when two threads act together. Say two threads are started in the main thread. Thread 1 executes method a.example(..) and Thread 2 executes a.show()

    Here the execution may very well be in the order as below.
    2,3,4,1
    Now the output is as below
    0
    true

    That means k is assigned before l.
    So this is not exactly what we wanted right?

    2> How to stop reordering?

    Ans. If the variables k and l are declared as volatile this reordering may be stopped.

    Let me rewrite the code again
    Code:
    class A{
    
        private volatile int k = 0;
        private volatile boolean l = false;
    
        public boolean getL(){
            return l;
        }
        public void example(int a, boolean b){
            k = a;//....  Line 1
            l = b;//....  Line 2
    
        }
        
        public void show(){
            System.out.println(k);//.... Line 3
            System.out.println(l);//.... Line 4
        }
    
        public static void main(String args[]){
    
            A a = new A();
            
            //code is omitted.
            /*a.example(3,true) is run in thread1*/
            /*a.show() is run in thread2*/
    
        }
    }
    Think about scenario 2. I repeat here: Thread 1 is executing a.example() and Thread 2 is executing a.show().
    Now one possible ordering may be as below
    1,3,4,2

    Then output is as below
    3
    False

    Here 1 has executed before 2. The reordering has been stopped. Because if the variables are volatile they are accessed in the same order as the code is written.

    But did we want this? We needed to see both the values 3 and "True" assigned.

    3> How to do this?

    Inside the run method of Thread 2 we may add this

    Code:
    if(a.getL()){
        a.show();
    }
    Here the lines executed by both the threads will be in following order
    1,2,3,4
    Also the output will be as follows
    3
    true

    4> Now one tricky question.

    Say we have 3 variables j,k and l. I write the class as follws

    Code:
    class A{
    
        private volatile int j = 0;
        private volatile int k = 0;
        private volatile boolean l = false;
        public void example(int a, boolean b){
            j = a;//....  Line 1
            k = a;//....  Line 2
            l = b;//....  Line 3
    
        }
        public boolean getL(){
            return l;
        }
        public void show(){
            System.out.println(j)//...  Line 4
            System.out.println(k);//.... Line 5
            System.out.println(l);//.... Line 6
        }
    
        public static void main(String args[]){
    
            A a = new A();
            
            //code is omitted.
            /*a.example(3,true) is run in thread1*/
            /*a.show() is run in thread2*/
    
        }
    }
    So if inside the run() method of thread 2 we write as the previous scenario

    Code:
    if(a.getL()){
        a.show();
    }
    The result will be ordered. Order of execution will be
    1,2,3,4,5,6 and output will be
    3
    3
    true

    Here is the question. For the same output can the order of execution be as below?
    2,1,3,4,5,6
    The answer is "Yes". So j and k must be assigned before l. But it is not necessary that j is assigned before k.

    So j and k may be non-volatile. Only l needs to be volatile.

    5> What is volatile?

    Answer:
    1> When a volatile variable is written into memory (assigned some value) it is ensured that all the previous assignments/memory writes in the code in the same thread must occur before this write of the volatile variable.
    2> Whenever volatile variable is read it must be read from memory. That's why it may see the value, which has been written just before this read.
    3> Whenever they are written they are written to memory rather than local cache of the thread.

    There are some other things about volatile. I will come up with them in my next article.
Working...