优惠券秒杀 - - 乐观锁悲观锁

451cfdcd912aa546c2b7b311c2ee4252893bb4fa

—————————————————————————————
问题一: 200线程,但只有100券,出现超卖现象
8e1cb4cc58c4d9b989e938c7728a8c0ce10a754e

beb9520fd8db01bda701c4b5da04880849a51c42

悲观锁(读少写多直接锁) 和 乐观锁(读多写少判断先)
b0e580fbd86f2738db7eeff14d040b8cfd98c5f1

乐观锁
法一: add version
bfab6e2ba228e4df8a532697f6d4d66aca33bd85

法二: cas法 (Compare-And-Swap)
1.判断是否等于查时的stock
e86f90ef1b91b9b7a2ae978e3e05807553d87dac
发现当所有人并行查询100时,只有第一个成功,
其他都无法取得,导致200个请求买100张,只抢到20张

2.判断是否还有余票
bec9cf8879bed7a0e693fd56eba5c5b0a5062639

总结
0dde1a199965da0cbf754e8934d63b5b15f29ea3

—————————————————————————–
对于大额优惠券,一人一单

大概思路:
1.直接锁用户的id.toString—>锁的是新new的String对象,不得行
2.锁id.toString.intern()—>根据常量池找相同内容的对象,锁的是同一个string
3.锁的范围应该是整个添加业务
4.锁的操作对象如果是this,那么事务会失效,
因为事务生效的前提: 调用者是spring的代理对象
98ce15581e31f8e3a74b6639d4938c7217c0bd28

——————————————————————————-
集群模式下, 同一个用户两次购买优惠券还是能够成功,无法做到一人一张.
究其根本, 一个SpringbootApplication有一个jvm虚拟机,且有唯一配套的锁监视器.
这种情况下跑多个线程是可以实现一人一张

但是如果有多个SpringbootApplication启动,就对应着多个jvm及其配套的锁监视器
如果同一用户走多个服务器发出请求,那么可能就会出现能买好多张的情况

8b32afccc0a5d81e1366cb635d5fdda6d13dcb8a

在单机环境下,通过 synchronized 或 JVM 内的锁机制可以保证同一用户在并发请求下“一人一单”。
但是在集群环境下,每个应用实例运行在独立 JVM 中,各自维护独立的锁对象,锁之间互不通信,
因此无法通过 JVM 内的锁来保证全局唯一性
也就是说,如果同一用户在不同实例(SpringApplication)上同时发起秒杀请求,
可能会成功创建多条订单,违反“一人一张”限制。