Content:
The problem of lock reentry
Abnormal release of lock
synchronized code block
The problem of lock reentry
The keyword synchronized has the function of lock reentry, that is to say, when using synchronized, when a thread gets the lock of an object, it can get the lock of the object again when requesting the object again.
Case 1:
package com.wuk.thread;
public class ThreadTest07 implements Runnable{
@Override
public void run() {
method1();
}
public synchronized void method1(){
System.out.println("method1...");
method2();
}
public synchronized void method2(){
System.out.println("method2...");
method3();
}
public synchronized void method3(){
System.out.println("method3...");
}
public static void main(String[] args) {
ThreadTest07 threadTest07=new ThreadTest07();
new Thread(threadTest07).start();
}
}
Result:
method1...
method2...
method3...
Case two:
Class Main
package com.wuk.thread;
public class Main {
public int i=10;
public synchronized void operationSup(){
i--;
System.out.println("Main print i="+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Class Sub
package com.wuk.thread;
public class Sub extends Main{
public synchronized void operationSub(){
while(i>0){
i--;
System.out.println("Sub print i="+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.operationSup();
}
}
}
package com.wuk.thread;
public class ThreadTest05 {
public static void main(String[] args) {
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
Sub sub=new Sub();
sub.operationSub();
}
});
t1.start();
}
}
Result:
Sub print i=9
Main print i=8
Sub print i=7
Main print i=6
Sub print i=5
Main print i=4
Sub print i=3
Main print i=2
Sub print i=1
Main print i=0
In case of exception, the lock will be released automatically
For web applications, if the lock is released abnormally, if not handled in time, it is likely to cause serious errors to the business logic of your application.
package com.wuk.thread;
public class ThreadTest06 implements Runnable{
private int num=0;
@Override
public void run() {
test();
}
public static void main(String[] args) {
ThreadTest06 threadTest06=new ThreadTest06();
new Thread(threadTest06,"threadTest06").start();
}
public synchronized void test(){
while (true){
num++;
if(num==10){
Integer.parseInt("q");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("num="+num);
}
}
}
synchronized code block
In some cases, the method using synchronized declaration has disadvantages. For example, if A thread substitutes synchronous method for A long time, then B thread can only wait. At this time, synchronized can be used to optimize execution time, that is, reduce the granularity of lock.
Case 1:
package com.wuk.thread;
public class ThreadTest08 {
public void method1(){
synchronized (this) {
System.out.println("do method1...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//Class lock
public void method2(){
synchronized (ThreadTest08.class) {
System.out.println("do method2...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private Object lock=new Object();
public void method3(){ //Any object lock
synchronized (lock) {
System.out.println("do method3...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final ThreadTest08 threadTest08=new ThreadTest08();
Thread thread01=new Thread(new Runnable() {
@Override
public void run() {
threadTest08.method1();
}
});
thread01.start();
Thread thread02=new Thread(new Runnable() {
@Override
public void run() {
threadTest08.method2();
}
});
thread02.start();
Thread thread03=new Thread(new Runnable() {
@Override
public void run() {
threadTest08.method3();
}
});
thread03.start();
}
}