Synchronized synchronization mechanism in Java multithreaded environment

1. Preface

Have you ever wondered if the ++ operation in Java is thread-safe, that is, if multiple threads execute the ++ operation together in a multi-threaded situation, the result will not be what we expected. You can write a demo to verify it.

public static int count = 0;
	
public static void main(String[] args) {
	for (int j = 0; j < 10000; j++) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				add();
			}
		}).start();
	}
	try {
		Thread.sleep(200);
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
	System.out.println(count);
}

public static void add(){
	count++;
}

The final execution results are as follows:

Clearly, the ++ operations in Java are not thread-safe.
This involves how thread security can be guaranteed when operating on the same variable or method in a multithreaded environment.

2. Synchronized

What is Synchronized?

Synchronized keyword is the use of a specific object to set a lock that allows only one thread to acquire and execute code when multithreaded concurrent access occurs, until the code is executed, the lock is released, and then competition continues with other threads.

Use of Synchronized

We can slightly alter the demo above to make ++ operations thread safe.

public static int count = 0;

public static void main(String[] args) {
	for (int j = 0; j < 10000; j++) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				add();
			}
		}).start();
	}
	try {
		Thread.sleep(200);
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
	System.out.println(count);
}

public synchronized static void add(){
	count++;
}

Just make a small change by adding the synchronized keyword to the add() method to see the results:


Multiple executions yielded 10,000 results, which was expected, and the **add()** method became a thread-safe method.

Scenarios for using Synchronized

Synchronized has three different usage scenarios and corresponds to different lock objects.

1.Synchronized Code Block

Modify the **add()** method of the demo above

public static void add(){
	Object o = new Object(); //Lock Object
	synchronized (o){
		count++;
	}
}

Define an Object object and use Object as the lock object. Only one thread will get the lock object and perform the ++ operation. When other threads need to wait for the lock object to be released, compete for the lock object so that the lock object can be acquired to proceed with the ++.

2.Synchronized method

public synchronized void add(){
		...
		...
}

What is the lock object for this add() method? Clearly, this is the current object, and the thread gets the current object.

3.Synchronized static methods

	public synchronized static void add(){
	count++;
}

The last one is the **add()** method in demo, in which case the lock object is the byte code object of the current class, because the static method belongs to this class, so the lock object is the byte code object of the current class.

summary

Synchronized Using in the code block, the lock object can be any object.
Synchronized In the method, the lock object is the current object this. 
Synchronized Using the static method, the lock object is the byte code object of the current class.

3. Common use of Synchronized classes

Vector is thread-safe, ArrayList, LinkedList is thread-insecure
Properties are thread-safe, HashSet, TreeSet are not
StringBuffer is thread-safe, StringBuilder is thread-insecure
HashTable is thread-safe, HashMap is thread-insecure

4. Summary

Synchronized can ensure data security for multithreaded data sharing, but if used improperly, threads hold lock objects for a long time and are not released in time, which can easily cause deadlock problems.
Also, Synchronized has a certain impact on performance, so be careful with Synchronized.

Thank you for watching. If it is helpful, please give us a pat on the back. Thank you.

Keywords: Java Back-end

Added by gandelf1000 on Mon, 03 Jan 2022 07:51:58 +0200