The use of synchronized in Java explains the four USES of of

  • 2020-04-01 04:21:06
  • OfStack

The keyword in the Java language, when used to modify a method or block of code, ensures that at most one thread executes the code at a time.

  1. The method statement to use when, after the scope operator (public, etc.), the return type declaration (void, etc.) before. At this time, the thread is a member of the lock, which can only have a thread into the method, at the same time, the other threads to invoke the method, can only wait in line, the current thread (that is, in a synchronized method of internal thread) after execute this method, other threads can enter.

Such as:


   public synchronized void synMethod() {
    //Method body
   }

      To use a block of code,synchronized is followed by parentheses, in which are variables, so that only one thread at a time enters the block.


   public int synMethod(int a1){
    synchronized(a1) {
     //Only one thread can enter at a time
    }
   }

      When an object is enclosed in parentheses, the thread acquires an object lock.


 public class MyThread implements Runnable {
  public static void main(String args[]) {
  MyThread mt = new MyThread();
  Thread t1 = new Thread(mt, "t1");
  Thread t2 = new Thread(mt, "t2");
  Thread t3 = new Thread(mt, "t3");
  Thread t4 = new Thread(mt, "t4");
  Thread t5 = new Thread(mt, "t5");
  Thread t6 = new Thread(mt, "t6");
  t1.start();
  t2.start();
  t3.start();
  t4.start();
  t5.start();
  t6.start();
 }
 public void run() {
  synchronized (this) {
   System.out.println(Thread.currentThread().getName());
  }
 }
} 

      For 3, if a thread enters and gets the current object lock, then no other thread can do anything on any of the objects in that class. Why lock the entire object and not allow other threads to access the Shared resource for a short time using other synchronized methods in the object? If an object has multiple resources, there is no need to lock all threads out just to have one thread use a portion of those resources. Since each object has a lock, you can use a virtual object to lock it as follows:


class FineGrainLock {
  MyMemberClass x, y;
  Object xlock = new Object(), ylock = new Object();
  public void foo() {
   synchronized(xlock) {
     //access x here
   }
   //do something here - but don't use shared resources
   synchronized(ylock) {
     //access y here
   }
  }
  public void bar() {
   synchronized(this) {
     //access both x and y here
   }
   //do something here - but don't use shared resources
  }
 }

  4. Synchronized is a class followed by a class in parentheses. At this point, the thread acquires an object lock.


class ArrayWithLockOrder{
 private static long num_locks = 0;
 private long lock_order;
 private int[] arr;
 public ArrayWithLockOrder(int[] a)
 {
  arr = a;
  synchronized(ArrayWithLockOrder.class) {//-- -- -- -- -- here
   num_locks++;       //Number of locks plus 1.
   lock_order = num_locks; //Set a unique lock_order for this object instance.
  }
 }
 public long lockOrder()
 {
  return lock_order;
 }
 public int[] array()
 {
  return arr;
 }
 }
 class SomeClass implements Runnable
 {
 public int sumArrays(ArrayWithLockOrder a1,
            ArrayWithLockOrder a2)
 {
  int value = 0;
  ArrayWithLockOrder first = a1;    //Keep one of the array references
  ArrayWithLockOrder last = a2;    //Local copy.
  int size = a1.array().length;
  if (size == a2.array().length)
  {
   if (a1.lockOrder() > a2.lockOrder()) //Determines and sets the locking of the object
   {                   //The order.
    first = a2;
    last = a1;
   }
   synchronized(first) {       //Lock objects in the correct order.
    synchronized(last) {
     int[] arr1 = a1.array();
     int[] arr2 = a2.array();
     for (int i=0; i<size; i++)
      value += arr1[i] + arr2[i];
    }
   }
  }
  return value;
 }
 public void run() {
  //
 }
 }

For 4, if the thread enters, the thread cannot perform all operations in the class, including static variables and static methods. In fact, for synchronization of code blocks with static methods and static variables, we usually use 4 to lock.

PS: summary of synchronized usage

Effects of synchronized on code in different places:

1. Methods to modify the synchronized keyword

Suppose that P1 and P2 are different objects of the same class, which defines synchronization blocks or synchronization methods in the following cases, so that P1 and P2 can both call them.


public synchronized void method(){
  // 
}

This is the synchronized method, and at this point the synchronized lock is calling the synchronized method object. In other words, when an object P1 executes this synchronization method in different threads, they will form mutual exclusion and achieve the effect of synchronization. Also, if there are more than one synchronized method in the object, when a thread executes a synchronized method in the object, no other synchronized method in the object is allowed to execute. But the Class to which this object belongs produces another object, P2, that can call this method with the synchronized keyword at will.

The sample code above is equivalent to the following:


public void method()  {  
  synchronized (this)   
  {  
    //..  
  }  
} 

This time is the object lock of a P1 object. Only the thread that gets the lock of the P1 object can call the synchronization method of P1. For P2, the lock of P1 has nothing to do with it.

2. Synchronization block, the sample code is as follows:


public void method() { 
synchronized (this) 
{ 
//.. 
} 
} 

In this case, the lock is the object so, and each object has a unique lock, so whoever gets the lock will be able to run the code he controls. This can be done when there is an explicit object as a lock, but when there is no explicit object as a lock and you just want to synchronize a piece of code, you can create a special instance variable (which must be an object) to act as a lock:


 private byte[] lock = new byte[0]; 
  Public void method(){  
      synchronized(lock) 
      { 
        // 
      }
  }  

Note: the zero-length byte array Object is more efficient to create than any other Object to see the compiled bytecode: only three opcodes are needed to generate a zero-length byte[] Object, whereas Object lock = new Object() requires seven lines of opcodes.

3. Apply synchronized to the static function as follows:


Class Foo  
{  
  public synchronized static void method1()  

  {  
    //.  
  }  
  public void method2()  
  {  
    synchronized(Foo.class)  
    //
  }  
} 

Both synchronous methods call a Class lock for the Class to which the method's object belongs (Class, not a specific object that is generated by the Class).
It can be inferred that if A class defines A static function A of synchronized and also defines A synchronized instance function B, then the same object Obj of that class will not be synchronized if it accesses methods A and B separately in multiple threads, because they have different locks. The lock for method A is the Class to which Obj belongs, and the lock for method B is the object to which Obj belongs.


Related articles: