Two ways and principle analysis of synchronized implementation of class lock in Java

Introduction

In the previous article "Two Ways and Principles of Synchronized Implementation of Object Locks in Java" , the two implementations of method locks and Synchronizedthe underlying principles were introduced. This article will explain synchronizedthe two implementations of class locks.

1. Definition of class lock

What is a class lock

类锁指synchronize修饰的静态方法或指定锁为class对象。

Where do class locks come from?

When different threads access methods that use class locks, the "locks" they acquire are actually Class objects. Because there is only one Class object in the same class, but there can be many other objects in the same class. At this point, there is a competition between multiple objects in the same class for the Class object, and the class lock ensures that only one thread is allowed to access the method locked by the class lock at the same time.

There are two ways to implement class locks:

  1. synchronizedAdded to the staticmethod (static method lock).
  2. synchronized(*.class) code block.

Next, let's take a look at the two implementations of class locks and the differences between them.

2. Implementing class locks by means of static method locks

When we use class locks, we should ensure that threads of different objects in the same class execute the same method, and ensure that multiple threads execute this method serially. It means that our class lock is in effect. With this expectation, let's take a look at the realization of multiple threads serially executing the target method through static method locks.

Complete code example:

public class ClassLock1 implements Runnable {

	// 这两个实例,声明为static,是因为要在main方法中测试,与方法锁无关
	static ClassLock1 instance1 = new ClassLock1();
	static ClassLock1 instance2 = new ClassLock1();

	// 关键: static synchronized两个关键字同时使用
	private static synchronized void method() {
		System.out.println("线程名:" + Thread.currentThread().getName() + ",运行开始");
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("线程:" + Thread.currentThread().getName() + ",运行结束");
	}

	@Override
	public void run() {
		method();
	}

	public static void main(String[] args) {
		Thread thread1 = new Thread(instance1);
		Thread thread2 = new Thread(instance2);
		thread1.start();
		thread2.start();
		try {
			//两个线程必须都执行完毕后
			thread1.join();
			thread2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("两个线程都已经执行完毕");
	}
}

operation result:

线程名:Thread-1,运行开始
线程:Thread-1,运行结束
线程名:Thread-0,运行开始
线程:Thread-0,运行结束
两个线程都已经执行完毕

2. Implementation principle of static method lock:

When you use synchronizedkeyword modification on static methods, you can think of method synchronization. But in fact, the second key point of using class locks is that when threads of different instances call methods in the class, that is, in the above code, the two threads in the main method thread1correspond thread2to the instance1sum instance2. The essence of this code is that two threads of two different objects ( instance1and instance2) in the same class need to use class locks to control the serial execution of these two threads. Then you may have the following questions: Why use class locks and what will happen with object locks?

Why use class locks and what about object locks?

First explain what the staticclass lock will become if it is not added? If you have read the previous article "Two Ways and Principles of Synchronized Implementing Object Locks in Java" , you will know:

synchronized能够保证在同一时刻最多只有一个线程执行该段代码,以保证并发安全。

But the only synchronizedmodified method is actually a method lock, that is, an object lock 对象锁的作用范围仅限于同一个对象内. In the above code, we have two different objects ( instance1and instance2), so if you remove the statickeyword, the synchronization method becomes a method lock in a different object, and because method lock is an implementation of object lock Form, that is, an object lock is held at this time instance1and respectively. instance2The characteristic of object lock is that the object lock of each object can only lock the threads in its own object, but cannot lock the threads in other objects, which is why the object lock cannot lock the threads in different objects. It is also the difference between object locks and class locks.

方法锁的作用范围是,同一个对象内的不同线程,而类锁则可以控制不同对象中的不同线程。

Why must be added to the synchronization method staticto achieve class lock?

After adding the keyword to the synchronization method static, the method is already initialized when the class is created. All instances in the class use this method synchronously, and the scope of the lock is the largest.

If the statickeyword is not added, the method will be accessed simultaneously with instance1and instance2, because the scope of the lock is only limited to the instance1and instance2object. At this time , synchronization with different threads where the two objects are located instance1can not be achieved .instance2

3. The synchronized (*.class) code block method implements class locks

The second implementation of class lock, its semantics are:

只要同步代码块中是*.class,不管有多少个对象调用这段代码,都表示大家共用一个对象,这就实现了不同的实例,串行的执行此代码块。

Complete code example:

public class ClassLock2 implements Runnable {

	static ClassLock2 instance1 = new ClassLock2();
	static ClassLock2 instance2 = new ClassLock2();

	@Override
	public void run() {
		method();
	}

	private void method() {
		//关键:用*.class作为锁对象,即使在不同的实例中,也能保证线程安全
		//对比:此形式类锁,与对象锁中的同步代码块锁,只有锁对象不同,同步代码块锁中的锁对象是this,而类锁是*.class)
		synchronized (ClassLock2.class) {
			System.out.println("线程名:" + Thread.currentThread().getName() + ",运行开始");
			try {
				Thread.sleep(4000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("线程:" + Thread.currentThread().getName() + ",运行结束");
		}
	}

	public static void main(String[] args) {
		Thread thread1 = new Thread(instance1);
		Thread thread2 = new Thread(instance2);
		thread1.start();
		thread2.start();
		try {
			//两个线程必须都执行完毕后
			thread1.join();
			thread2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("两个线程都已经执行完毕");
	}

}

operation result

线程名:Thread-0,运行开始
线程:Thread-0,运行结束
线程名:Thread-1,运行开始
线程:Thread-1,运行结束
两个线程都已经执行完毕

It can be seen that the two threads are still executed serially, which is consistent with the result of the previous method.

Why does Java's synchronizedimplementation of class lock or object lock provide two ways?

The two ways are: using synchronizeddecorated methods or using synchronizedcode blocks.

The reason for providing both ways is because synchronizedone of the pitfalls of keywords is inefficiency.

synchronized只有当同步方法执行完或执行时抛出异常或调用wait系列方法时,才会释放锁。若不释放锁,其他线程只能等待,所以相对相率比较低。

The first principles of improving efficiency in doing anything are:

在满足要求的情况下,尽可能的少做事

Therefore synchronized, in addition to the keyword can be added to the method, it also provides a synchronized code block, which can be used inside the method. When writing a program, we should reduce the amount of code in the code block as much as possible while meeting the requirements synchronized, because the synchronizedcode in the code block is executed serially, and the efficiency is naturally not as efficient as parallel processing by multiple threads. Therefore, the code that does not need synchronization should be moved to synchronizedexecute outside the code block, which will be more efficient. That's synchronizedwhy there are two ways to do synchronization.

4. Summary

This article undertakes the above "two ways and principle analysis of synchronized implementation of object lock in Java" after explaining the object lock, and then explains the class lock. synchronizedThe various implementations of object locks and class locks implemented in Java have been explained clearly, and their implementation principles have also been preliminarily analyzed.

synchronizedBut these are only the basic parts. In the next article, we will focus on analyzing whether thread safety can be guaranteed in different situations in 7, and thoroughly understand synchronizedthe scope of keywords, so that we can no longer use synchronization in the process of digging holes for ourselves. And in the follow-up article, the interviewer often asks about the scene, which is absolutely not to be missed. If you like this article, please like and subscribe.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324147849&siteId=291194637