什么是可重入锁
在Java多线程编程中,锁是用来控制代码操作的原子性的重要机制,即对某线程共享的数据进行操作的时候,保证该操作同一时间段只有一个线程操作,整个过程是原子操作,其他线程再操作的时候只能等待锁的释放(排他锁)。一般我们的锁都是声明在方法上或者代码块中,那么在实际编程中我们经常会出现一个类的实例方法调用另一个实例方法的情况,我们不希望这个时候同一个线程进入另一实例方法时还要再去等待锁的释放,可重入锁就是为了解决这个问题,即 线程可以进入任何一个它已经拥有的锁所同步着的代码块。
如何实现一个简单的可重入锁
- 首先加锁的时候需要记录当前是哪一个线程加锁,加锁之后加锁标志位标记锁已被占用
- 维护一个加锁计数器,线程每次加锁计数器都要加1,每释放一次计数器减1
- 当非占用锁的线程进来之后自旋等待锁的释放,如果锁还在被占用,就wait();
- 所释放的时候只有当前获取锁的线程调用才有用,锁释放加锁计数器减1,当减到0的时候,加锁标志位置为false,然后唤醒其他等待的线程
1 | public class MyLock implements Lock { |
在Java中常用的可重入锁
- synchronized 关键字加锁
- java.util.concurrent.locks.ReentrantLock
- java.util.concurrent.locks.ReentrantReadWriteLock
上述ReentrantLock内部实际上还是使用AQS,关于AQS,后面还要进行学习与整理