1、最原始的解决:
上面代码存在的问题:1、当红色框中抛出异常时,key无法被删除,导致其他的线程的result一直未false,于是有了下面一版:
2、将删除key的操作放在finally中
上述代码存在的问题:如果在执行红色框中代码时,电脑突然宕机,那么后面获取到的result值也永远时false,于是想到需要给key设置一个过期时间
3、
上述代码存在的问题:如果执行了第一句还没来得及执行第二句宕机,依旧会加超时过期失败,于是有下面一个版本
4、将下面一行当做原子命令执行
如果并发量不是很大的情况下,上述方案已经够用,但是如果在高并发场景下,会有其他的问题
比如第一个线程执行需要15s,当执行到10s时,key被删除,第二个线程进来,执行8s后,第一个线程执行完成,释放锁,此时释放的是第二个线程加的锁,于是第三个线程也可以进来,执行5s后,第二个线程将第三个线程的锁释放掉,这样就会造成锁永久失效的问题,于是有下面一个版本
5、上述代码根本原因就是自己加的锁被别的线程释放,所以给每个线程生成一个随机的uuid,释放锁时获取uuid进行判断之后再释放
上述代码存在的问题:假设执行到第三步之前耗时9.9s(注意过期时间为10s),第三步执行完成,到第四步出现了小的卡顿,还没来得及释放锁,结果锁到了过期时间自动被释放,然后第二个线程进来加锁成功,此时第一个线程的第4步开始执行,释放锁,依旧释放的不是自己的锁,也会出现问题。
为了解决上述问题,已经有很成熟的中间件redisson
6、利用redisson解决分布式锁问题
Redisson加锁逻辑:
Redisson中间件实现的分布式锁性能非常好,底层利用lua脚本保证原子性