Java class lock object lock private lock conflict test

  • 2020-04-01 03:30:01
  • OfStack

Do class and object locks conflict? Do object locks and private locks conflict? It is illustrated by examples.

I. relevant agreements

In order to clarify the following description, the relevant definitions of locks involved in this paper are agreed as follows:

Class locks: methods in code with static and synchronized locks, or synchronized(xxx.class) code segments, increament();

2. Object lock: a lock with synchronized or a snippet of synchronized(this) to a method in the code, as in synOnMethod() and synInMethod();

3. Private lock: declare a private property inside the class, such as private Object lock, in the code segment that needs to be locked, synchronized(lock), as synMethodWithObj() below.

Two, test code

1. Write a startup class called ObjectLock


public class ObjectLock {
 public static void main(String[] args) {
  System.out.println("start time = " + System.currentTimeMillis()+"ms");
  LockTestClass test = new LockTestClass();
  for (int i = 0; i < 3; i++) {
   Thread thread = new ObjThread(test, i);
   thread.start();
  }
 }
}

2. Write a thread class ObjThread to start the synchronization method (note that its run method may be tweaked for different tests)


public class ObjThread extends Thread {
 LockTestClass lock;
 int i = 0;  public ObjThread(LockTestClass lock, int i) {
  this.lock = lock;
  this.i = i;
 }  public void run() {
  //No lock method
//  lock.noSynMethod(this.getId(),this);
  //Object lock method 1, in the manner of synchronized synInMethod
  lock.synInMethod();
  //Object lock method 2, in the manner of synchronized(this)
//  lock.synOnMethod();
  //Private lock method, in the form of synchronized(object)
//  lock.synMethodWithObj();
  //Class lock method, in the form of static synchronized increment
  LockTestClass.increment();
 }
}

3. Write another LockTestClass, LockTestClass, with various locking methods


public class LockTestClass {
 //Used for class lock count
 private static int i = 0;
    //Private lock
 private Object object = new Object();  /**
  * <p>
  * Unlocked method
  *
  * @param threadID
  * @param thread
  */
 public void noSynMethod(long threadID, ObjThread thread) {
  System.out.println("nosyn: class obj is " + thread + ", threadId is"
    + threadID);
 }  /**
  * Object lock method 1
  */
 public synchronized void synOnMethod() {
  System.out.println("synOnMethod begins" + ", time = "
    + System.currentTimeMillis() + "ms");
  try {
   Thread.sleep(2000L);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  System.out.println("synOnMethod ends");
 }  /**
  * Object lock method 2, using synchronized (this) To lock
  */
 public void synInMethod() {
  synchronized (this) {
   System.out.println("synInMethod begins" + ", time = "
     + System.currentTimeMillis() + "ms");
   try {
    Thread.sleep(2000L);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("synInMethod ends");
  }  }  /**
  * Object lock method 3
  */
 public void synMethodWithObj() {
  synchronized (object) {
   System.out.println("synMethodWithObj begins" + ", time = "
     + System.currentTimeMillis() + "ms");
   try {
    Thread.sleep(2000L);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("synMethodWithObj ends");
  }
 }  /**
  * Kind of lock
  */
 public static synchronized void increament() {
  System.out.println("class synchronized. i = " + i + ", time = "
    + System.currentTimeMillis() + "ms");
  i++;
  try {
   Thread.sleep(2000L);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
   System.out.println("class synchronized ends.");
 } }

Iii. Test results

1. Test the class lock and object lock. The run method of ObjectThread is modified as follows:


public void run() {
  //No lock method
//  lock.noSynMethod(this.getId(),this);
  //Object lock method 1, in the manner of synchronized synInMethod
  lock.synInMethod();
  //Object lock method 2, in the manner of synchronized(this)
//  lock.synOnMethod();
  //Private lock method, in the form of synchronized(object)
//  lock.synMethodWithObj();
  //Class lock method, in the form of static synchronized increment
  LockTestClass.increament();
 }

Terminal output:


start time = 1413101360231ms
synInMethod begins, time = 1413101360233ms
synInMethod ends
class synchronized. i = 0, time = 1413101362233ms
synInMethod begins, time = 1413101362233ms
class synchronized ends.
synInMethod ends
class synchronized. i = 1, time = 1413101364233ms
synInMethod begins, time = 1413101364233ms
class synchronized ends.
synInMethod ends
class synchronized. i = 2, time = 1413101366234ms
class synchronized ends.

You can see that the object lock method (synInMothod) is 2 seconds faster than the class lock method (increament) the first time it is started because the increament was executed after the sleep of 2 seconds during the execution of synInMehtod. The two methods share a thread and are 2 seconds slower.

When the class lock method is started, the object lock method of another thread is also started almost at the same time, indicating that the two are not using the same lock, will not produce competition.

Conclusion: there is no competition between class lock and object lock.

2. Private lock and object lock. The run method of ObjectThread is modified as follows:


public void run() {
  //No lock method
//  lock.noSynMethod(this.getId(),this);
  //Object lock method 1, in the manner of synchronized synInMethod
  lock.synInMethod();
  //Object lock method 2, in the manner of synchronized(this)
//  lock.synOnMethod();
  //Private lock method, in the form of synchronized(object)
  lock.synMethodWithObj();
  //Class lock method, in the form of static synchronized increment
//  LockTestClass.increament();
 }

Terminal output:


start time = 1413121912406ms
synInMethod begins, time = 1413121912407ms.
synInMethod ends.
synMethodWithObj begins, time = 1413121914407ms
synInMethod begins, time = 1413121914407ms.
synInMethod ends.
synMethodWithObj ends
synInMethod begins, time = 1413121916407ms.
synMethodWithObj begins, time = 1413121916407ms
synInMethod ends.
synMethodWithObj ends
synMethodWithObj begins, time = 1413121918407ms
synMethodWithObj ends

Very similar to class and object locks.

Conclusion: private locks and object locks do not compete, and their methods of locking do not affect each other.

3. Synchronized is directly added to methods and synchronized(this), and the run method of ObjectThread is modified as follows:


public void run() {
  //No lock method
//  lock.noSynMethod(this.getId(),this);
  //Object lock method 1, in the manner of synchronized synInMethod
  lock.synInMethod();
  //Object lock method 2, in the manner of synchronized(this)
  lock.synOnMethod();
  //Private lock method, in the form of synchronized(object)
//  lock.synMethodWithObj();
  //Class lock method, in the form of static synchronized increment
//  LockTestClass.increament();
 }

Terminal output:


start time = 1413102913278ms
synInMethod begins, time = 1413102913279ms
synInMethod ends
synInMethod begins, time = 1413102915279ms
synInMethod ends
synOnMethod begins, time = 1413102917279ms
synOnMethod ends
synInMethod begins, time = 1413102919279ms
synInMethod ends
synOnMethod begins, time = 1413102921279ms
synOnMethod ends
synOnMethod begins, time = 1413102923279ms
synOnMethod ends

As you can see, both are strictly serialized (of course, whether to run synInMethod first or synOnMethod first when executed again is not certain, depending on who gets the lock).

Conclusion: both synchronized(this) and synchronized(this) are methods that add a lock to the current object.


Related articles: