Multithreading in Java : Part III

What will I learn?

This tutorial covers following topics:

  • Thread Synchronization
  • Thread Synchronization with synchronized method

Requirements

  • A laptop/PC with Mac OS/ Linux/ Windows
  • Preinstalled OpenJDK
  • Preinstalled jvm
  • Preinstalled Code editor

Difficulty

Intermediate, you must have good knowledge of basics of Java programming to catch up this tutorial.

Tutorials Content

In previous tutorials, we learned two ways of creating threads in Java:by extending thread class and by implementing runnable interface. While executing a program with
multiple threads there may come a situation at any time that two or more threads want to use same resources. For example, one thread may be writing data to a file, other may be erasing
the data from the same file at the same time. This may result in conflicts and the output may be different from it should have been.
To solve this problem we need to allow only one thread to use a specific resource at a specific time period. Thus we need to synchronize the execution of the threads to handle the situation.
We can synchronize multiple threads by making internal communication between threads, using the synchronized method or using the synchronized block.

Synchronization in Java is based on an internal concept of lock which is also known as monitor. Each object in Java is associated with a lock while executing the object holds the
lock and free it when the thread finishes its work. Executing a multithreaded program without synchronization produces the different output each time we execute the program whereas
with synchronization it produces the same result.

by synchronized method

Let us see a multithreading example without using the synchronized method. We will see the same example in both cases(using or without using synchronized method) to understand the synchronization. This example prints odd numbers from 1-10 and 1-20.

    class Oddnum{ 
    defining method which is not synchronized   
    void printoddnum(int n){
    //loop
       for(int i=1;i<=n;i+=2){
               System.out.println(i);
           }  
         try{  
         //sleep method from thread class
          Thread.sleep(500);  
         }catch(Exception e){System.out.println(e);}  
       }  
      
     }  
     //creating class which extends thread
    class Thread1 extends Thread{  
        Oddnum o;
        Thread1(Oddnum o){
            //this keyword to refer current object 
            this.o=o;
        }
        
        public void run(){
        o.printoddnum(10);
        
    }
      
    }  
    class Thread2 extends Thread{    
        Oddnum o;
        Thread2(Oddnum o){
            this.o=o;
        }
        
        public void run(){
        o.printoddnum(20); 
    
    }  
    }  
      
    class ThreadTesting{  
    //main method
    public static void main(String args[]){  
    //Creating object to access Oddnum class
    Oddnum object = new Oddnum();
    //creating thread
    Thread1 t1 = new Thread1(object);  
    Thread2 t2 = new Thread2(object);  
    //starting thread by invoking run()
    t1.start();  
    t2.start();  
    }  
    } 

Output:

run:
1
3
5
7
9
11
13
15
17
19
1
3
5
7
9
BUILD SUCCESSFUL (total time: 0 seconds)

Running the same program again:
Output:

1
3
5
7
9
1
3
5
7
9
11
13
15
17
19
BUILD SUCCESSFUL (total time: 0 seconds)

As we can see, they are not in same order, running the same program again will result different order of output.

Now the same program using the synchronized method. The synchronized method is any method that starts with synchronized.
Synchronized method locks the object for the resources which needs to be shared. As mentioned earlier, using the synchronized method in Threads locks the object and free it when the thread finishes its task.

class Oddnum{  
     //defining synchronized method
    synchronized void printoddnum(int n){ 
       for(int i=1;i<=n;i+=2){
               System.out.println(i);
           }  
         try{  
          Thread.sleep(500);  
         }catch(Exception e){System.out.println(e);}  
       }  
      
     }  
    class Thread1 extends Thread{  
        Oddnum o;
        Thread1(Oddnum o){
            this.o=o;
        }
        
        public void run(){
        o.printoddnum(10);
        
    }
      
    }  
    class Thread2 extends Thread{    
        Oddnum o;
        Thread2(Oddnum o){
            this.o=o;
        }
        
        public void run(){
        o.printoddnum(20); 
    
    }  
    }  
      
    class ThreadTesting{  
    public static void main(String args[]){  
    Oddnum object = new Oddnum();
    Thread1 t1 = new Thread1(object);  
    Thread2 t2 = new Thread2(object);  
    t1.start();  
    t2.start(); 
    }  
    }  

Running this program again and again we get same order in output:

run:
1
3
5
7
9
1
3
5
7
9
11
13
15
17
19
BUILD SUCCESSFUL (total time: 1 second)

All above codes can be found on my GitHub link. Click here to download.

What's next?

  • Thread Synchronization using synchronized block
  • Comparision of synchronized method and block
  • Communication between threads
  • Thread priority and more.

CURRICULAM

Multithreading in Java : Part I

Multithreading in Java : Part II



Posted on Utopian.io - Rewarding Open Source Contributors

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now
Logo
Center