java中锁机制_Java中的锁机制——可重入锁(递归锁)

目录

什么是可重入锁(递归锁)

sychronized版

lock版

为什么可重入锁能防止死锁

什么是可重入锁(递归锁)

可重入锁也叫递归锁。它指的是同一个线程在外层获取锁之后,内层方法也会自动获取锁。lock和sychronized都是可重入锁

可重入锁最大的作用就是避免死锁

bb47c54da0801cca063db5d8cf82ab70.png

看这个小例子,method01和02都是加锁的方法,根据可重入锁的原理,线程只要获得了01的锁就能访问02,即使02也是个带锁的方法。

c9934a9b81cd6fc08a1897c160d448cd.png

sychronized版

一个同步方法可进入另外一个同步方法

// Synchronized

public class Demo01 {

public static void main(String[] args) {

Phone phone = new Phone();

new Thread(() -> {

phone.sms();

}, "A").start();

new Thread(() -> {

phone.sms();

}, "B").start();

}

}

class Phone {

public synchronized void sms() {

System.out.println(Thread.currentThread().getName() + "sms");

call(); // 这里也有锁

}

public synchronized void call() {

System.out.println(Thread.currentThread().getName() + "call");

}

}

lock版

sms方法是一个lock锁方法,这个方法调用了call方法,而call方法也是个lock锁方法。可重入锁指一个线程只要能进入sms方法,就也能进入到call方法中

public class Demo02 {

public static void main(String[] args) {

Phone2 phone = new Phone2();

new Thread(() -> {

phone.sms();

}, "A").start();

new Thread(() -> {

phone.sms();

}, "B").start();

}

}

class Phone2 {

Lock lock = new ReentrantLock();

public void sms() {

lock.lock(); // 细节问题:lock.lock(); lock.unlock(); // lock 锁必须配对,否则就会死在里面

try {

System.out.println(Thread.currentThread().getName() + "sms");

call(); // 这里也有锁

} catch (Exception e) {

e.printStackTrace();

} finally {

lock.unlock();

}

}

public void call() {

lock.lock();

try {

System.out.println(Thread.currentThread().getName() + "call");

} catch (Exception e) {

e.printStackTrace();

} finally {

lock.unlock();

}

}

}

为什么可重入锁能防止死锁

这里举一个经典的例子。

public class Widget {

public synchronized void doSomething(){

// do something

}

}

public class LoggingWidget extends Widget {

public synchronized void doSomething() {

super.doSomething();

}

}

现在假设synchronized不是可重入锁。

Widget方法执行需要获得sync锁,默认情况下sync锁的是this,LoggingWidget是Widget的子类。当你执行LoggingWidget中的super.doSomething方法时它就会获得父类的this锁,但父类的this锁被子类抢走之后,没了锁就没法执行完毕。

这样就出现死锁的现象,子类让父类执行完释放锁,而父类的锁在子类这里没法执行完毕。

现在synchronized是可重入锁

当进入到LoggingWidget方法时,即使LoggingWidget方法里面有一另一个锁也没关系,它也能获得Widget类中的内容,由于Widget类执行完毕了,LoggingWidget便可以继续执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值