The article shares 4 examples of detailed explanation of synchronized
1. Whether to add synchronized keywords
public class ThreadTest { public static void main(String[] args) { Example example = new Example(); Thread t1 = new Thread1(example); Thread t2 = new Thread1(example); t1.start(); t2.start(); }}class Example { public synchronized void exhaust() { for (int i = 0; i < 5; ++i) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("excute:" + i); } }}class Thread1 extends Thread { private Example example; public Thread1(Example example) { this.example = example; } @Override public void run() { example.excute(); }}The output result of the synchronized keyword is as follows
A set of 0-4 will be output first, and then the next set will be output, and the two threads will be executed in sequence.
Excute:0
Excute:1
Excute:2
Excute:3
Excute:4
Excute:0
Excute:1
Excute:2
Excute:3
Excute:4
The output result of the synchronized keyword is as follows
Two threads execute the excute method simultaneously and concurrently
Excute:0
Excute:0
Excute:1
Excute:1
Excute:2
Excute:2
Excute:3
Excute:3
Excute:4
Excute:4
2. Multi-threading situation of multiple methods
public class ThreadTest { public static void main(String[] args) { Example example = new Example(); Thread t1 = new Thread1(example); Thread t2 = new Thread2(example); t1.start(); t2.start(); }}class Example { public synchronized void exhaust() { for (int i = 0; i < 5; ++i) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("excute:" + i); } } public synchronized void exhaust1() { for (int i = 0; i < 5; ++i) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("excute1:" + i); } }}class Thread1 extends Thread { private Example example; public Thread1(Example example) { this.example = example; } @Override public void run() { example.excute(); }}class Thread2 extends Thread { private Example example; public Thread2(Example example) { this.example = example; } @Override public void run() { example.excute1(); }}The execution results are as follows
The same is executed in sequence, and one thread is executed before another thread is executed.
Excute:0
Excute:1
Excute:2
Excute:3
Excute:4
Excute1:0
Excute1:1
Excute1:2
Excute1:3
exclusive1:4
If the synchronized keyword is removed, the two methods are executed concurrently and have no mutual influence.
But as written in the example subroutine, even two methods:
The execution result is always the output of one thread and then the execution of another thread.
illustrate:
If an object has multiple synchronized methods, and a thread has entered a synchronized method at a certain moment, then other threads cannot access any synchronized methods of the object before the method is executed.
in conclusion:
When the synchronized keyword modifies a method, the method is called the synchronization method.
Each object in Java has a lock, or a monitor. When a thread accesses the synchronized method of an object, the object is locked, and no other thread can access the synchronized method of the object (here refers to all synchronization methods, not just the same method). It is not until the previous thread completes the execution method (or throws an exception), the lock of the object is released, so that other threads can access the synchronized method of the object again.
Note that the object is locked at this time. If it is a different object, there is no restriction relationship between the objects.
When trying to construct a second thread object in the code, a new Example object is passed in, then there is no restriction between the execution of the two threads.
3. Static synchronization method
When a synchronized keyword modified method is also modified by static, it has been said before that a non-static synchronization method will lock the object, but the static method does not belong to the object, but a class, and it will lock the Class object of the class where this method is located.
public class ThreadTest { public static void main(String[] args) { Example example = new Example(); Example example2 = new Example(); Thread t1 = new Thread1(example); Thread t2 = new Thread2(example2); t1.start(); t2.start(); }}class Example { public synchronized static void exhaust() { for (int i = 0; i < 5; ++i) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("excute:" + i); } } public synchronized static void exhaust1() { for (int i = 0; i < 5; ++i) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("excute1:" + i); } }}class Thread1 extends Thread { private Example example; public Thread1(Example example) { this.example = example; } @Override public void run() { example.excute(); }}class Thread2 extends Thread { private Example example; public Thread2(Example example) { this.example = example; } @Override public void run() { example.excute1(); }}The execution results are as follows
Excute:0
Excute:1
Excute:2
Excute:3
Excute:4
Excute1:0
Excute1:1
Excute1:2
Excute1:3
exclusive1:4
If there is no static modifier, and two threads pass different objects, they will be executed concurrently at the same time.
So if it is a static method (execute() and execute2() both have static keywords added), even if different Example objects are passed to two threads, the two threads are still restricted by each other. One must be executed first and then the next one.
in conclusion:
If a synchronized method is static, when a thread accesses the method, it locks not the object where the synchronized method is located, but the Class object corresponding to the class where the synchronized method is located. In Java, no matter how many objects a class has, these objects will correspond to a unique Class object. Therefore, when a thread accesses two static and synchronized methods of two objects of the same class, their execution order is also sequential, that is, one thread executes the method first, and the other thread starts after the execution is completed.
4. Synchronized block
synchronized(object)
{
}
It means that the thread will lock the object object when it is executed. (Note that this object can be an object of any class, or you can use this keyword).
This way, you can specify the locked object by yourself.
public class ThreadTest { public static void main(String[] args) { Example example = new Example(); Thread t1 = new Thread1(example); Thread t2 = new Thread2(example); t1.start(); t2.start(); }}class Example { public void exhaust() { synchronized (this) { for (int i = 0; i < 5; ++i) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("excute:" + i); } } } public void exhaust1() { synchronized (this) { for (int i = 0; i < 5; ++i) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("excute1:" + i); } } } } }}class Thread1 extends Thread { private Example example; public Thread1(Example example) { this.example = example; } @Override public void run() { example.excute(); }}class Thread2 extends Thread { private Example example; public Thread2(Example example) { this.example = example; } @Override public void run() { example.excute1(); }}The execution results are as follows
Excute:0
Excute:1
Excute:2
Excute:3
Excute:4
Excute1:0
Excute1:1
Excute1:2
Excute1:3
exclusive1:4
The effect achieved by Example Program 4 is the same as that of Example Program 2. Both threads are executed in sequence, rather than concurrently. When one thread executes, the object object is locked, and the other thread cannot execute the corresponding block.
The synchronized method is actually equivalent to wrapping all statements in the method with a synchronized block, and then passing this keyword in the brackets of the synchronized block. Of course, if it is a static method, the class object needs to be locked.
Perhaps only a few lines of code in a method will involve thread synchronization issues, so the synchronized block controls the access of multiple threads more granularly than the synchronized method. Only the content in the synchronized block cannot be accessed by multiple threads at the same time, and other statements in the method can still be accessed by multiple threads at the same time (including before and after the synchronized block).
in conclusion:
The synchronized method is a coarse-grained concurrent control. At a certain moment, only one thread can execute the synchronized method;
Synchronized block is a fine-grained concurrency control, which only synchronizes the code in the block. Other codes located in the method and other than synchronized blocks can be accessed by multiple threads at the same time.
The above is about the Synchronized block synchronization method of Java multi-threaded programming. I hope it will be helpful to everyone's learning.