单纯的 Redis 分布式锁仍然有些场景不满⾜的,如⼀个⽅法获取到锁后,可能在⽅法内继续调这个⽅法,就获取不到锁了。这时就要把锁改进成可重⼊锁。
重⼊锁,是以线程为单位,当⼀个线程获取对象锁后,该线程还可再次获取该对象上的锁,⽽其它线程不可以。可重⼊锁是为防⽌死锁。
注:在java的编程中synchronized 和 ReentrantLock都是可重入锁。
为每个锁关联⼀个请求计数器和⼀个占有它的线程。当计数为0,认为锁未被占有。
线程请求⼀个未被占有的锁时,JVM将记录锁的占有者,并将请求计数器置1。
若同⼀线程再请求该锁,计数将递增 每次占⽤线程退出同步块,计数器值将递减。直到计数器为0, 锁被释放
⽗类和⼦类的锁的重⼊:⼦类重写⽗类的 synchonized ⽅法,然后调⽤⽗类中的⽅法,此时若没有重⼊锁,这段代码将死锁。
如下图使用redisson加锁后会在redis中创建一个hash类型的数据,其中redisKey是order,key是线程的线程id+线程获取锁的次数,value是线程获取锁的次数。
redis首先记录抗住并发,然后多线程将redis的记录同步到mysql,最后再使用业界熟悉的本地事务+mq消息表进行消费,来保证最终一致性。