可重入锁
指的是通过线程外层函数获得锁之后,内层递归函数仍然能够获得该锁的代码,在一个线程外层方法获取锁的时候,在进入内层方法自动获取锁。
也就是说,线程可以进入任何一个已经拥有的锁所同步着的代码块
ReentranLock/Synchronized就是一个很典型的可重入锁,作用避免死锁
上代码
package com.example.demo;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Phone implements Runnable {
public synchronized void SendSMS() throws Exception {
System.out.println(Thread.currentThread().getId() + "\t invock SendSMS().....");
SendEmail();
}
public synchronized void SendEmail() throws Exception {
System.out.println(Thread.currentThread().getId() + "\t ###########invock SendEmail().....");
}
Lock lock = new ReentrantLock();
@Override
public void run() {
get();
}
public void get() {
try {
lock.lock();
lock.lock();
//线程可以进入任何一个已经拥有的锁所同步着的代码块
System.out.println(Thread.currentThread().getId() + "\t invock get().....");
set();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
lock.unlock();
}
}
public void set() {
try {
lock.lock();
System.out.println(Thread.currentThread().getId() + "\t ##########invock set().....");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class ReenterLockDemo {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(() -> {
try {
phone.SendSMS();
} catch (Exception e) {
e.printStackTrace();
}
}, "t1").start();
new Thread(() -> {
try {
phone.SendSMS();
} catch (Exception e) {
e.printStackTrace();
}
}, "t2").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println();
System.out.println();
System.out.println();
System.out.println();
System.out.println();
Thread t3 = new Thread(phone);
Thread t4 = new Thread(phone);
t3.start();
t4.start();
}
}
运行结果:
12 invock SendSMS().....
12 ###########invock SendEmail().....
13 invock SendSMS().....
13 ###########invock SendEmail().....
14 invock get().....
14 ##########invock set().....
15 invock get().....
15 ##########invock set().....
总结:ReentranLock/Synchronized 是java开发中常见的可重入锁也叫做递归锁,通过代码验证,在调用get方法中,如果去掉get方法中其中的一个 lock.unlock(); 还会成功吗?答案显而易见不会成功,15 这把锁会被锁住卡在那里,并不会被输出....切记两两配对,加几次锁几次....