转自:码农翻车(微信ID:coderising)1.无所旺财和小强生活在一个网上商城系统中,他们是线程的好朋友。周一刚上班,旺财接到领导电话说某产品库存需要减20,旺财不敢怠慢,赶紧拿出库存一看,哦,现在有1000.与此同时,小强也接到一个电话,说要将同款商品的库存减少30个,他一看,哦,现在有1000个。旺财计算最新库存值980,救!小强还计算了最新库存值970,救!旺财的数据被小强覆盖了!领导看到原本卖了50件,现在库存只扣了30件。再这样下去,天下就乱了。旺才和小强各打20板,记性好长!2、悲观的锁小强说:“哥,我们不如想想办法,再这样下去,我们会被活活打死的。”旺财伤心地说:“这样一来,以后每次访问库存,都要先加锁,加了锁,其他人就不能访问了,只能等持有锁的人了释放它。”周二,领导要求旺财再次降库存20。旺财这次很小心,先锁定了存货,然后慢慢修改。小强也接到了减少库存的命令,但是旺财哥已经锁定了库存无法操作,小强只好先去堵车车间喝茶聊天,然后去备货车间等待调度操作。好不容易等到可以再次执行的时候,小强才看到这个存货还是锁着的!?只好又去堵车车间喝茶。领导一看,小强,你怎么了,老是喝茶聊天?!你还在工作吗?小强辩解说旺财哥一直在锁存货,我操作不了。不管这些,领导又把小强和旺才打了20下。(备注:这种加锁方式就是悲观锁,悲观锁就像它的名字一样,每次读写数据,总以为数据会被别人修改,所以给数据加锁,让其处于加锁状态防止别人读写访问。缺点是如果持有锁的时间太长,其他用户要等很久。)3.乐观锁王才说:“兄弟,对不起你这一次,处理的比较慢,不过小弟刚才被打的时候,想到了一个好办法:乐观锁。”小强说:“拉下来,你屁股都快被砸了还看好?”》听我说,我们在库存字段旁边,加上上一个版本(version)的字段,比如一开始(库存=1000,版本=1),每次去读不仅是库存,还要版本号,等你修改库存的时候,一定要在倒着写的时候检查一下版本号,看和读的时候是不是一样。”“如果不一样怎么办?”小强问道,“那就放弃这次写操作,重新读取库存和版本号,重新开始。”“如果一样呢?”“那你放心把新的写回去大胆盘点存货价值。“版本号也加1”“我好像有点明白了,你试试看,不过你想想,我不想再被登机了。”周三,旺财被勒令减去30从库存中,他首先读取(stock=1000,version=1);,版本=1)。旺财计算出新的存货价值970,写回成功。现在版本变为(库存=970,版本=2)。小强又算了一个新的库存值950,正准备写回去。他浑身发抖,看到最新的版本号,已经变成2版了,按照之前的约定,只好又看了一遍。小强又看了一遍(stock=970,version=2),计算出最新的缓存值920(970减50),再次尝试更新,没想到被别人抢占了,现在版本号变成了3,最新的数据是(库存=900,版本=3)。唉,只好从头再来,计算最新的缓存值为850(900减50),第三次更新终于成功了。最新库存为(库存=850,版本=4)。搞砸了,满意地点点头:好同志。(备注:这个方法就是所谓的乐观锁,旺财和小强这次比较乐观一点,他们认为一般情况下修改库存的人不会太多,所以没有加锁,用confidence,并且只在最后一次更新时检查是否有冲突。这种方式适用于冲突少的场景。如果冲突多,数据争用激烈,会导致不断尝试,会降低性能。。)
