1.可重入锁,也叫递归锁,值得是同一线程外部函数获取锁之后,内层递归函数仍然能获取该锁的代码,
在同一个线程外层方法获取锁的时候,在进入内层方法会自动获取锁;
就是,线程可以进入任何一个它已经拥有的锁所同步着的代码块;
ReentrantLock和synchronized这两种就是可重入锁;
public class ReenterLockDemo {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(new Runnable() {
@Override
public void run() {
phone.sendMsg();
}
},"t1").start();
new Thread(new Runnable() {
@Override
public void run() {
phone.sendMsg();
}
},"t2").start();
}
}
class Phone{
public synchronized void sendMsg(){
System.out.println(Thread.currentThread().getName()+"\t invoke sendMsg()");
sendEmail();
}
public synchronized void sendEmail(){
System.out.println(Thread.currentThread().getName()+"\t -----invoke sendEmail");
}
}
结果是:
t1 invoke sendMsg()
t1 -----invoke sendEmail
t2 invoke sendMsg()
t2 -----invoke sendEmail
从这第一个demo,可以证明 synchronized 是 可重入锁; 同理下面验证一下ReentrantLock的可重入性;
public class ReenterLockDemo {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(new Runnable() {
@Override
public void run() {
phone.get();
}
},"t1").start();
new Thread(new Runnable() {
@Override
public void run() {
phone.get();
}
},"t2").start();
}
}
class Phone{
ReentrantLock lock = new ReentrantLock();
public void get(){
try{
lock.lock();
System.out.println(Thread.currentThread().getName()+"\t -------------invoke get");
set();
}finally {
lock.unlock();
}
}
public void set(){
try{
lock.lock();
System.out.println(Thread.currentThread().getName()+"\t -------------------invoke set()");
}finally {
lock.unlock();
}
}
}
结果:
t1 -------------invoke get
t1 -------------------invoke set()
t2 -------------invoke get
t2 -------------------invoke set()
Process finished with exit code 0
lock.lock(),如果加两次错,释放两次锁,也是正确;
但是得对应的也得释放两次锁,枷锁几次,释放几次;
如果只加一次,释放两次会报错,加两次,释放一次,程序会被阻塞