测试案例
id | name | money |
---|---|---|
1 | 小明 | 1000 |
小明的账户上有1000 元 ,现在有两个线程同时往他账户上加钱。
1.A 线程准备往小明的账户上加100, 1, 读取到小明 有 1000 元, 1000 + 100 事务未提交;
2.B 线程准备往小明的账户上加200, 1, 读取到小明 有 1000 元 ,1000 + 200 事务未提交;
3.A 线程提交事务 小明账户余额变成1100, 但这时B 线程还不知道小明账户余额变成1100了;
id | name | money |
---|---|---|
1 | 小明 | 1100 |
4.B 线程提交事务 小明账户余额变成1200。
id | name | money |
---|---|---|
1 | 小明 | 1200 |
A 线程的更新丢失 本来余额应该是1300,结果余额变成1200
加锁的目的在于保障 一个线程修改数据时这个数据没有被其他线程改过。
一、何为乐观锁与悲观锁
乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。
二、悲观锁悲观锁 适合短事务(长事务导致其它事务一直被阻塞,影响系统性能),查少该多。
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁,保证了数据安全。(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
三、乐观锁
乐观锁 适合查多改少,经常被并发修改的数据可能老是出现版本不一致导致有的线程操作常常失败。
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁。但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。乐观锁适用于多读的应用类型,这样可以提高吞吐量。增加并发量
四、两种锁的使用场景
1.乐观锁 适合查多改少,经常被并发修改的数据可能老是出现版本不一致导致有的线程操作常常失败。
2.悲观锁 适合短事务(长事务导致其它事务一直被阻塞,影响系统性能),查少该多。
五、总结
并没有什么乐观锁比 悲观锁好,它们所适应的是不用的场景。你可以根据你的业务选择合适的锁。