基于数据库
- 悲观锁
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。
优点:是比较安全的一种实现方法。
缺点:在高并发的场景下开销是不能容忍的。容易出现数据库死锁等情况。 - 乐观锁
乐观锁常常用于分布式系统对数据库某张特定表执行update操作。考虑线上选座的场景,用户A和B同时选择了某场次电影的一个座位,都去将座位的状态设置为已售。
设想这样的执行序列:
1、用户A判断该座位为未售状态;
2、用户B判断该座位为未售状态;
3、用户A执行update座位为已售;
4、用户B执行update座位为已售。
这样会出现同一个座位售出两次的情况,解决方案是在这张数据库表中增加一个版本号的字段。执行操作前读取当前数据库表中的版本号,在执行update语句时将版本号放在where语句中,如果更新了记录则说明成功,如果没有更新记录,则说明此次update失败。
加了乐观锁的执行序列:
1、用户A查询该座位,得到该座位是未售状态,版本号是5;
2、用户B查询该座位,得到该座位