可重入锁

旧城等待, 2022-05-21 10:35 353阅读 0赞

原文:https://www.shiyanlou.com/questions/2460

1 . 什么是可重入锁

锁的概念就不用多解释了,当某个线程A已经持有了一个锁,当线程B尝试进入被这个锁保护的代码段的时候.就会被阻塞.而锁的操作粒度是”线程”,而不是调用(至于为什么要这样,下面解释).同一个线程再次进入同步代码的时候.可以使用自己已经获取到的锁,这就是可重入锁java里面内置锁(synchronize)和Lock(ReentrantLock)都是可重入的

2 . 为什么要可重入

如果线程A继续再次获得这个锁呢?比如一个方法是synchronized,递归调用自己,那么第一次已经获得了锁,第二次调用的时候还能进入吗? 直观上当然需要能进入.这就要求必须是可重入的.可重入锁又叫做递归锁,再举个例子.

  1. public class Widget {
  2. public synchronized void doSomething() {
  3. ...
  4. }
  5. }
  6. public class LoggingWidget extends Widget {
  7. public synchronized void doSomething() {
  8. System.out.println(toString() + ": calling doSomething");
  9. super.doSomething();//若内置锁是不可重入的,则发生死锁
  10. }
  11. }

这个例子是java并发编程实战中的例 子.synchronized 是父类Widget的内置锁,当执行子 类的方法的时候,先获取了一次Widget的锁,然后在执行super的时候,就要获取一次,如果不可重入,那么就跪了.

3 . 如何实现可重入锁

为每个锁关联一个获取计数器和一个所有者线程,当计数值为0的时候,这个所就没有被任何线程只有.当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取计数值置为1,如果同一个线程再次获取这个锁,技术值将递增,退出一次同步代码块,计算值递减,当计数值为0时,这个锁就被释放.ReentrantLock里面有实现

4 . 有不可重入锁吗

这个还真有.Linux下的pthread_mutex_t锁是默认是非递归的。可以通过设置PTHREAD_MUTEX_RECURSIVE属性,将pthread_mutex_t锁设置为递归锁。如果要自己实现不可重入锁,同可重入锁,这个计数器只能为1.或者0,再次进入的时候,发现已经是1了,就进行阻塞.jdk里面没有默认的实现类.

5 . demo代码展示

5.1 内置锁的可重入

  1. public class ReentrantTest {
  2. public void method1() {
  3. synchronized (ReentrantTest.class) {
  4. System.out.println("方法1获得ReentrantTest的内置锁运行了");
  5. method2();
  6. }
  7. }
  8. public void method2() {
  9. synchronized (ReentrantTest.class) {
  10. System.out.println("方法1里面调用的方法2重入内置锁,也正常运行了");
  11. }
  12. }
  13. public static void main(String[] args) {
  14. new ReentrantTest().method1();
  15. }
  16. }

5.2 lock对象的可重入

  1. import java.util.concurrent.locks.Lock;
  2. import java.util.concurrent.locks.ReentrantLock;
  3. public class ReentrantLockTest {
  4. private Lock lock = new ReentrantLock();
  5. public void method1() {
  6. lock.lock();
  7. try {
  8. System.out.println("方法1获得ReentrantLock锁运行了");
  9. method2();
  10. } finally {
  11. lock.unlock();
  12. }
  13. }
  14. public void method2() {
  15. lock.lock();
  16. try {
  17. System.out.println("方法1里面调用的方法2重入ReentrantLock锁,也正常运行了");
  18. } finally {
  19. lock.unlock();
  20. }
  21. }
  22. public static void main(String[] args) {
  23. new ReentrantLockTest().method1();
  24. }
  25. }

6. 参考文章

  • 可重入锁测试
  • 生产者消费者的一个更真实的例子
  • 浅谈Java中的锁
  • java并发编程实战

发表评论

表情:
评论列表 (有 0 条评论,353人围观)

还没有评论,来说两句吧...

相关阅读

    相关

              可重入锁的设计目的是为了防止死锁。例如在多个方法互相调用的场景,需要保证可重入,不然很容易死锁。           java中的synchronized

    相关

    原文:https://www.shiyanlou.com/questions/2460 1 . 什么是可重入锁 锁的概念就不用多解释了,当某个线程A已经持有了一个锁,当

    相关 与非

    可重入锁与非可重入锁 可重入锁又称递归锁,是指同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提是锁对象得是同一个对象),不会因为之前已经获