总结
超卖本质问题:线程A读 —> 线程A 写 的过程中,有其他线程插入进去了。
保证: 线程A读 —> 线程A写 -----> 线程B读 ------> 线程B写, 线程读写没有其他线程插进去。
超卖解决有哪些:
悲观锁,分布式锁,乐观锁,队列串行化,Redis原子操作(也是保证读和写是一个原子,没有其他线程插入)
库存超卖如何产生的?
超卖本质问题:线程A读 —> 线程A 写 的过程中,有其他线程插入进去了。
如:
- 线程A读 —> 线程B读 ------> 线程A写 ------> 线程B写
- 线程A读 —> 线程B读 ------> 线程B写 ------> 线程A写
下面是一个超卖示意图:
线程A读 —> 线程B读 ------> 线程A写 ------> 线程B写
12 > 10 12 > 10 12 - 10 = 2 2 - 10 = -8
线程操作时,数据库是真实改变了的。
图片来源:https://zhuanlan.zhihu.com/p/87106151
保证什么就可以不发生超卖?
保证: 线程A读 —> 线程A写 -----> 线程B读 ------> 线程B写
不让单个线程写的时候有其他线程插进去。
最近总结,发现凡是多线程操作共享变量的,一定要保证: (线程读+线程写)绑在一起,中间不允许其他线程插入。无论是分布式锁,悲观锁,还是乐观锁都是保证(线程读+线程写)绑在一起,只是实现的方式不一样。
分布式锁怎么解决?
加分布式锁解决办法:
图片来源:https://zhuanlan.zhihu.com/p/87106151
lock.lock() ---- > 线程A读 —> 线程A写 ----> lock.unlock()
看吧,就是为保证(线程A读 —> 线程A写)的过程中,不能有其他线程的乱入。
什么是分布锁:
(只要保证所有线程可见,锁有两种状态就能实现锁,分布式锁只不过是分布式环境下,模块不在同一个JVM中,要用存在缓存,数据库,zookeeper这种不在一个JVM中的模块都能访问的变量作为锁)
分布式锁优化解决高并发:
分段锁的思想:参考:面试官:每秒上千订单的场景下,如何对分布式锁进行高并发优化?
悲观锁(mysql事务控制(数据库行锁) + redis队列)怎么解决?
其实分布式锁就是悲观锁。
mysql的执行代码:
beginTranse