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

Introduction

This article will introduce two types of object locks in Java and how to implement them. They are synchronized code block locks and method locks, respectively. We will solve the thread unsafe problem mentioned in the previous article "Thread Safety and Thread Unsafe Analysis and Examples in Java"synchronized , and see how to easily solve the problem by passing object locks.

1. Synchronized code block lock

Case: By synchronizing the code block lock, two threads execute the same global variable count10,000 times each count++to verify whether the result is equal to 20,000, and there will be no case of less than 20,000.

Complete code implementation:

public class SynchronizeCodeBlockLock implements Runnable {
	private static SynchronizeCodeBlockLock instance = new SynchronizeCodeBlockLock();
	private static int count = 0;

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

	private void method() {
		// 关键:同步代码块的方式,操作同一变量,达到线程安全的效果
		synchronized (this) {
			System.out.println("线程名:" + Thread.currentThread().getName() + ",运行开始");
			for (int i = 0; i < 10000; i++) {
				count++;
			}
			System.out.println("线程:" + Thread.currentThread().getName() + ",运行结束");
		}
	}

	public static void main(String[] args) {
		Thread thread1 = new Thread(instance);
		Thread thread2 = new Thread(instance);
		thread1.start();
		thread2.start();
		while (thread1.isAlive() || thread2.isAlive()) {
			// 若有线程如果还在活动,则不执行下一步(等同于thread.join()方法)
		}
		System.out.println("期待结果:20000,实际结果:" + count);
	}


}

operation result:

线程名:Thread-0,运行开始
线程:Thread-0,运行结束
线程名:Thread-1,运行开始
线程:Thread-1,运行结束
期待结果:20000,实际结果:20000

Analyze the running results:

We found that synchronizedafter using the keyword, thread Thread-0 executes first, and after it ends, Thread-1 starts executing. If the synchronizedkeyword is not used, the execution result may be that Thread-0 and Thread-1 are executed almost at the same time, and the operation ends at almost the same time. This means that synchronizedafter using the keyword, the parallelism of multiple threads is changed to serial.

2. Method lock

This example only shows the method lock, an example of serial execution in the control thread. The effect of method locks to ensure thread safety is the same as that of synchronized code blocks.

public class MethodLock implements Runnable {

	private static MethodLock instance = new MethodLock();

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

	//关键:synchronized可以保证此方法被顺序执行,线程1执行完4秒钟后,线程2再执行4秒。不加synchronized,线程1和线程2将同时执行
	private synchronized void method() {
		System.out.println("线程:" + Thread.currentThread().getName() + ",运行开始");
		try {
			//模拟执行一段操作,耗时4秒钟
			Thread.sleep(4000);
			System.out.println("线程:" + Thread.currentThread().getName() + ",运行结束");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		// 模拟:同一个对象下,两个线程,同步执行一个方法(串行执行则为线程安全,并行执行,则为线程不安全,)
		Thread thread1 = new Thread(instance);
		Thread thread2 = new Thread(instance);
		thread1.start();
		thread2.start();
		while (thread1.isAlive() || thread2.isAlive()) {

		}
		System.out.println("测试结束");
	}
}

operation result:

线程:Thread-0,运行开始
线程:Thread-0,运行结束
线程:Thread-1,运行开始
线程:Thread-1,运行结束
测试结束

It is found that in the running result, multiple threads are also executed serially, and the effect is consistent with the synchronized code block lock.

3. How does the synchronized keyword ensure thread safety?

All objects in Java will have a lock, called a built-in lock, also known as a monitor lock. This is an exclusive lock.

排他锁:一个线程获取后,其他线程只能等待其释放后,才有机会获得该锁。

Every object in Java can use the built-in lock as a synchronization lock. When a thread enters the synchronizedcode block, it will automatically acquire the monitor lock. At this time, when other threads access the synchronizedcode block, they will be blocked and suspended (meaning being rejected). The thread that gets the lock will release the lock when the execution is completed, or when an exception is thrown, or when the wait series method is called. Other threads can only acquire the lock after waiting for the lock to be released.

In layman's terms, the synchronizedkeyword converts the code in the code block from 并行to 串行, thus ensuring that the code is executed sequentially.

4. At the memory level, how does synchronized achieve locking and releasing locks?

  • When entering synchronizeda code block, the variables used in the code block are cleared from the thread's working memory and retrieved from the main memory instead.
  • When the code block is exited synchronized, the modifications to the variables used in the code block are flushed to main memory.

This is actually the principle of synchronizedsolving shared variables . 内存可见性Regarding synchronizedthe properties (visibility, reentrancy), I will explain in detail in other subsequent articles.

5. Synchronized turns the parallel processing of threads into serial processing, what are the disadvantages?

synchronizedChanging parallel to serial will of course affect the execution efficiency of the program, and the execution speed will be affected. Secondly, synchronizedthe blocking of the operation thread, that is, the context switching performed by the operating system controlling the CPU core, is also time-consuming. So using synchronizedkeywords will reduce the efficiency of the program.

6. What should I pay attention to when using the Synchronized keyword?

1. When using Synchronized, you need to pay attention that the lock object cannot be empty.

The information of the lock object is retained in the object header. If the object is empty, the lock information does not exist.

2. The scope should not be too large

The amount of code in the synchronized code block should not be too much. If too much code is placed in it, the operation of the program will become serial and the speed will decrease. The parallelism of each thread can improve efficiency. We should only put those codes that affect thread safety into synchronized code blocks and execute them serially; no need to consider thread-safe codes, execute them in parallel to achieve the highest efficiency.

3. Avoid deadlocks

Avoid situations where threads hold and wait on locks (a follow-up article will explain deadlocks).

7. Summary

This article explains two implementations of object locks in Java, which are the following two implementations:

Method 1: Synchronized code block lock:

synchronized (共享变量) {
    //需要同步的代码
}

Method 2: Method lock:

	private synchronized void method() {
	    //需要同步的代码
	}

No matter which form you use, you should minimize the content of synchronized code while ensuring synchronization, which can improve the running efficiency of the program and ensure thread safety. If you like this article, please like and subscribe, and welcome to continue reading other multi-threaded articles in this column.

Guess you like

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