什么是可重入锁?

971 阅读3分钟

可重入锁是一种能够让同一个线程多次获取同一把锁的锁,也就是说,如果一个线程已经持有了某个锁,那么它可以再次请求这个锁而不会被阻塞或者产生死锁。可重入锁可以降低编程的复杂性,避免一些潜在的错误,提高并发性能。

可重入锁的实现原理

可重入锁的实现原理是为每个锁关联一个请求计数器和一个持有者线程。当计数器为0时,表示该锁没有被任何线程持有,此时任何线程都可以请求这个锁,如果成功获取,将会把计数器设为1,同时记录持有者为当前线程。当同一个线程再次请求这个锁时,计数器会递增,而不会进行阻塞或者竞争;当持有者释放这个锁时,计数器会递减,如果计数器为0,则表示该锁已经完全释放,此时其他线程可以竞争获取该锁。

可重入锁的优缺点

  • 防止死锁:如果一个线程在持有一个锁的同时,又要请求另一个已经被自己持有的锁,如果这个锁不是可重入的,那么就会发生死锁。例如,在Java中,synchronized关键字修饰的方法或代码块就是可重入的,如果一个线程在调用一个同步方法时,又要调用另一个同步方法(无论是同一个类中还是继承关系中),那么它可以继续执行而不会被阻塞。
  • 提高封装性:可重入锁可以让代码更加简洁和清晰,不需要考虑获取和释放锁的顺序和次数,也不需要额外的变量来判断是否已经持有某个锁。

可重入锁的缺点

  • 增加开销:可重入锁需要记录持有者和请求次数,这些信息需要占用一定的内存空间,并且在获取和释放锁时需要进行一些额外的操作。相比之下,不可重入锁就简单得多,只需要一个标志位来表示是否被占用即可。
  • 可能导致活跃性问题:如果一个线程长时间持有一个可重入锁,并且频繁地请求和释放该锁,那么可能导致其他等待该锁的线程长时间得不到执行机会,从而降低系统的吞吐量和响应性。

可重入锁的应用场景

  • 递归调用:如果一个方法需要递归地调用自身或者其他方法,并且这些方法都需要同步保护,那么使用可重入锁可以避免反复获取和释放同一把锁,提高效率和可读性。
  • 继承关系:如果一个类继承了另一个类,并且覆盖了父类中的某些同步方法,在子类中调用父类的同步方法时,使用可重入锁可以保证子类和父类之间的同步逻辑正确和一致。