可重入\不可重入锁?

待我称王封你为后i 2022-08-31 01:45 301阅读 0赞

一、不可重入锁

不可重入锁是指当前线程执行中已经获取了锁,如果再次获取该锁时,就会被阻塞。

下面我们以wait/notify来设计一个不可重入锁(此外还可以通过CAS + 自旋来实现):

  1. //wait、notify实现不可重入锁
  2. public class NonReentrantLockDemo1 {
  3. //记录是否被锁
  4. private volatile boolean locked = false;
  5. public synchronized void lock() {
  6. //当某个线程获取锁成功,其他线程进入等待状态
  7. while (locked) {
  8. try {
  9. wait();
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. }
  13. }
  14. //加锁成功,locked 设置为 true
  15. locked = true;
  16. }
  17. //释放锁
  18. public synchronized void unlock() {
  19. locked = false;
  20. notify();
  21. }
  22. }
  23. //测试类
  24. class ThreadDemo implements Runnable{
  25. NonReentrantLockDemo lock = new NonReentrantLockDemo();
  26. public static void main(String[] args) {
  27. new Thread(new ThreadDemo()).start();
  28. }
  29. /** * 方法1:调用方法2 */
  30. public void method1() {
  31. lock.lock();
  32. try {
  33. System.out.println(Thread.currentThread().getName() + " method1()");
  34. method2();
  35. } finally {
  36. lock.unlock();
  37. }
  38. }
  39. /** * 方法2:打印前获取 obj 锁 * */
  40. public void method2() {
  41. lock.lock();
  42. try {
  43. System.out.println(Thread.currentThread().getName() + " method2()");
  44. } finally {
  45. lock.unlock();
  46. }
  47. }
  48. @Override
  49. public void run() {
  50. method1();
  51. }
  52. }

在这里插入图片描述
结果显示:当线程执行到method1时,已经拿到lock锁,只要该锁没有被释放,其他代码块无法使用此锁来加锁。当该线程再去调用method2时,而method2也需要获取lock才能执行,这样都导致了死锁,这种会出现问题的重入一把锁的情况,叫不可重入锁。

二、可重入锁

可重入锁又叫递归锁,指在同一个线程在外层方法获取锁的时候,进入内层方法会自动获取锁。

这里使用一段代码简单演示ReentrantLock可重入:

  1. private static ReentrantLock lock = new ReentrantLock();
  2. public static void main(String[] args) {
  3. System.out.println(lock.getHoldCount());
  4. lock.lock();
  5. System.out.println(lock.getHoldCount());
  6. lock.lock();
  7. System.out.println(lock.getHoldCount());
  8. lock.unlock();
  9. System.out.println(lock.getHoldCount());
  10. lock.unlock();
  11. System.out.println(lock.getHoldCount());
  12. }
  13. 0
  14. 1
  15. 2
  16. 1
  17. 0

结果显示:同一个线程获取到ReentrantLock锁后,在不释放该锁的情况下可以再次获取。

可重入性优点:

  • 避免死锁
  • 提升封装性

发表评论

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

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

相关阅读