Synchronization in Java multithreading

Posted by Pests on Fri, 11 Feb 2022 04:28:30 +0100

Multithreaded programs may often encounter situations where multiple threads try to access the same resources and eventually produce errors and unpredictable results.

Therefore, some synchronization method is needed to ensure that only one thread can access resources at a given point in time. Java A method of creating threads and synchronizing their tasks using synchronization blocks is provided. Synchronization blocks in Java are marked with the synchronized keyword. Synchronization blocks in Java synchronize on an object. All synchronization blocks synchronized on the same object can execute only one thread at a time. All other threads trying to enter the synchronization block are blocked until the thread in the synchronization block exits the block.

The following is the general form of synchronization block:

// Only one thread can execute at a time. 
// sync_object is a reference to an object
// whose lock associates with the monitor. 
// The code is said to be synchronized on
// the monitor object
synchronized(sync_object)
{
   // Access shared variables and other
   // shared resources
}

This synchronization is implemented in Java through a concept called monitor. Only one thread can have a monitor at a given time. When a thread obtains a lock, it is said to have entered the monitor. All other threads attempting to enter the lock monitor will be suspended until the first thread exits the monitor.

The following is an example of multithreading with synchronization.

// A Java program to demonstrate working of
// synchronized.

import java.io.*;
import java.util.*;

// A Class used to send a message
class Sender
{
  public void send(String msg)
  {
    System.out.println("Sending\t" + msg );
    try
    {
      Thread.sleep(1000);
    }
    catch (Exception e)
    {
      System.out.println("Thread interrupted.");
    }
    System.out.println("\n" + msg + "Sent");
  }
}

// Class for send a message using Threads
class ThreadedSend extends Thread
{
  private String msg;
  Sender sender;

  // Receives a message object and a string
  // message to be sent
  ThreadedSend(String m, Sender obj)
  {
    msg = m;
    sender = obj;
  }

  public void run()
  {
    // Only one thread can send a message
    // at a time.
    synchronized(sender)
    {
      // synchronizing the snd object
      sender.send(msg);
    }
  }
}

// Driver class
class SyncDemo
{
  public static void main(String args[])
  {
    Sender snd = new Sender();
    ThreadedSend S1 =
      new ThreadedSend( " Hi " , snd );
    ThreadedSend S2 =
      new ThreadedSend( " Bye " , snd );

    // Start two threads of ThreadedSend type
    S1.start();
    S2.start();

    // wait for threads to end
    try
    {
      S1.join();
      S2.join();
    }
    catch(Exception e)
    {
      System.out.println("Interrupted");
    }
  }
}

output

Sending     Hi 

 Hi Sent
Sending     Bye 

 Bye Sent

Every time we run the program, the output is the same.

In the above example, we chose to synchronize the Sender object in the run() method of the ThreadedSend class. Alternatively, we can define the entire send() block as synchronous and produce the same result. Then we don't have to synchronize the Message object in the run() method of the ThreadedSend class.

// An alternate implementation to demonstrate
// that we can use synchronized with method also.

class Sender {
   public synchronized void send(String msg)
   {
       System.out.println("Sending\t" + msg);
       try {
           Thread.sleep(1000);
       }
       catch (Exception e) {
           System.out.println("Thread interrupted.");
       }
       System.out.println("\n" + msg + "Sent");
   }
}

We don't have to always synchronize the entire method. Sometimes it's best to synchronize only part of the method. Method can achieve this.

// One more alternate implementation to demonstrate
// that synchronized can be used with only a part of  
// method

class Sender  
{
   public void send(String msg)
   {
       synchronized(this)
       {
           System.out.println("Sending\t" + msg );
           try  
           {
               Thread.sleep(1000);
           }  
           catch (Exception e)  
           {
               System.out.println("Thread interrupted.");
           }
           System.out.println("\n" + msg + "Sent");
       }
   }
}

This article is an original article from big data to artificial intelligence blogger "xiaozhch5", which follows the CC 4.0 BY-SA copyright agreement. Please attach the original source link and this statement for reprint.

Original link: https://lrting.top/backend/3752/