Synchronized block synchronization method for Java multithreaded programming

  • 2020-04-01 04:27:07
  • OfStack

The article shares detailed explanations of synchronized with four examples

1. Difference of whether to add the synchronized keyword or not


public class ThreadTest {

  public static void main(String[] args) {
    Example example = new Example();

    Thread t1 = new Thread1(example);
    Thread t2 = new Thread1(example);
    t1.start();
    t2.start();
  }
}

class Example {
  public synchronized void excute() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute:" + i);
    }

  }

}

class Thread1 extends Thread {
  private Example example;

  public Thread1(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute();
  }
}

The output with the synchronized keyword is as follows

The first set of 0-4 is output, and then the next set is output, and the two threads execute sequentially

Excute: 0
Excute: 1.
Excute: 2
Excute: 3
Excute: 4
Excute: 0
Excute: 1.
Excute: 2
Excute: 3
Excute: 4

The output without the synchronized keyword is as follows

Both threads execute the excute method simultaneously and concurrently

Excute: 0
Excute: 0
Excute: 1.
Excute: 1.
Excute: 2
Excute: 2
Excute: 3
Excute: 3
Excute: 4
Excute: 4

2. Multi-threading of multiple methods


public class ThreadTest {

  public static void main(String[] args) {
    Example example = new Example();

    Thread t1 = new Thread1(example);
    Thread t2 = new Thread2(example);
    t1.start();
    t2.start();
  }
}

class Example {
  public synchronized void excute() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute:" + i);
    }
  }
  public synchronized void excute1() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute1:" + i);
    }
  }

}

class Thread1 extends Thread {
  private Example example;

  public Thread1(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute();
  }
}

class Thread2 extends Thread {
  private Example example;

  public Thread2(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute1();
  }
}

The results are as follows

It is also executed sequentially, executing one thread before another

Excute: 0
Excute: 1.
Excute: 2
Excute: 3
Excute: 4
Excute1:0
Excute1:1.
Excute1:2
Excute1:3
Excute1:4

If the synchronized keyword is removed, the two methods execute concurrently and do not affect each other.

But as the example shows, even two methods:

The result of execution is always the execution of the output of one thread followed by the execution of another thread.

Description:

If an object has multiple synchronized methods, and at some point a thread has entered a synchronized method, no other thread can access any of the object's synchronized methods until the method completes execution.

Conclusion:

When the synchronized keyword modifies a method, the method is called a synchronized method.

Each object in Java has a lock (lock), or a monitor (monitor), when a thread object access a synchronized method, the object is locked, no other threads are unable to visit the object of a synchronized method (here refers to all of the synchronized methods, not just the same way), until the thread after the execution method (or throw exceptions), to release the object's lock, other threads can be synchronized method to access the object.

Note that the object is locked, and if it is a different object, there is no restrictive relationship between the objects.

When you pass in a new Example object when you try to construct a second thread object in your code, there are no constraints between the execution of the two threads.

3. Static synchronization method

When a method modified by the synchronized keyword is also static, as mentioned earlier, a non-static synchronized method locks an object, but a static method does not belong to an object, it belongs to a Class, and it locks the Class object of the Class in which the method resides.


public class ThreadTest {

  public static void main(String[] args) {
    Example example = new Example();
    Example example2 = new Example();
    Thread t1 = new Thread1(example);
    Thread t2 = new Thread2(example2);
    t1.start();
    t2.start();
  }
}

class Example {
  public synchronized static void excute() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute:" + i);
    }
  }
  public synchronized static void excute1() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute1:" + i);
    }
  }

}

class Thread1 extends Thread {
  private Example example;

  public Thread1(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute();
  }
}

class Thread2 extends Thread {
  private Example example;

  public Thread2(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute1();
  }
}

The results are as follows

Excute: 0
Excute: 1.
Excute: 2
Excute: 3
Excute: 4
Excute1:0
Excute1:1.
Excute1:2
Excute1:3
Excute1:4

If there is no static modifier, two threads pass in different objects and execute concurrently

So if it's a static method case (execute() and execute2() with the static keyword), even if you pass two different Example objects to two threads, they're still mutually exclusive and must execute one before the next.

Conclusion:

If a synchronized method is static, when a thread accesses the method, it locks not the object that the synchronized method is in, but the Class object that the synchronized method is in. In Java, no matter how many objects a Class has, those objects correspond to a unique Class object, so when a thread accesses two static, synchronized methods of two objects of the same Class, they execute in sequence, meaning that one thread executes the method first, and the other thread does not start until it finishes.

4. The synchronized block

Synchronized (object)

{       

}

Means that the thread locks the object when it executes. Note that this object can be an object of any class, or you can use the this keyword.

This allows you to specify which objects to lock.


public class ThreadTest {

  public static void main(String[] args) {
    Example example = new Example();
    Thread t1 = new Thread1(example);
    Thread t2 = new Thread2(example);
    t1.start();
    t2.start();
  }
}

class Example {
  public void excute() {
    synchronized (this) {
      for (int i = 0; i < 5; ++i) {
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("excute:" + i);
      }
    }
    
  }
  public void excute1() {
    synchronized (this) {
      for (int i = 0; i < 5; ++i) {
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("excute1:" + i);
      }
    }
    
  }

}

class Thread1 extends Thread {
  private Example example;

  public Thread1(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute();
  }
}

class Thread2 extends Thread {
  private Example example;

  public Thread2(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute1();
  }
}

The results are as follows

Excute: 0
Excute: 1.
Excute: 2
Excute: 3
Excute: 4
Excute1:0
Excute1:1.
Excute1:2
Excute1:3
Excute1:4

Example program 4 The effect is the same as in example 2, which is to make two threads execute in order, not concurrently, so that when one thread executes, the object is locked, and the other thread cannot execute the corresponding block.

A synchronized method is effectively equivalent to enclosing all the statements in a method with a synchronized block, then passing the this keyword in parentheses of the synchronized block. Of course, if it is a static method, it is the class object that needs to be locked.

Only a few lines of code of a method might involve thread synchronization problem, so the synchronized blocks more fine-grained than synchronized methods to control the access of multiple threads, only the contents of the synchronized block cannot be accessed by multiple threads at the same time, other statements in the method still can access by multiple threads at the same time (including the synchronized block before and after).

Conclusion:

Synchronized methods Is a coarse-grained concurrency control in which only one thread can execute the synchronized method at a time.

Synchronized blocks It is a fine-grained concurrency control that only synchronizes the code in a block, so that code that is inside a method or outside a synchronized block can be accessed by multiple threads at the same time.

The above is about Java multi-threaded programming Synchronized block synchronization method, hope to help you learn.


Related articles: