正文
老老实实地进入锁池里待着去吧!
等到隔壁小明做完了事情, 美滋滋的拿着最新的value值出来以后, 我们这99个在锁池里吹牛的线程一跃而起,去竞争那个刚刚被释放的锁。
但是下一个幸运儿是谁呢? 不知道?
有时候人类为了公平,会搞个队列让我们排好队,先进先出。 但是我已经活了4.998秒,人生快走到了尽头, 在这么长的人生里, 我体会到的真理是: 公平实在是个稀缺货,不公平才是常态!
所以年轻人不要老是抱怨这个社会, 没用的, 还是老老实实的奋斗吧。
平淡的日子就这么过着, 有一天线程世界来了一个年轻人,自称为小李, 他看着我们这么努力地奋斗着去争抢那把锁, 不由地嘲笑道: 你们真傻啊, 难道不知道不加锁也能做事吗?
我们愣了一下,人群中立刻发出一阵爆笑:哈哈哈, 这小子疯了,没有锁岂不又回到互相覆盖数据的日子了!
小李不甘示弱:你们这帮土老帽,把元老院的那帮老家伙的话当做圣旨, 岂不知天外有天, 人外有人, 这世界大得很呐!
这句话把我们镇住了, 我小心翼翼地问: 那你说说,不加锁怎么才能保证正确性呢?
“就拿你们的那个Sequence类来说吧, 不就是并发的更新内存中的一个值吗, 可以这么分为三步来做:
1. 从内存中读取value 值,假设为10, 我们把这个值称为A
2. B = A+1 得到 B = 11
3. 用A 和 内存的值相比, 如果相等(就是说在过去的一段时间,没人修改内存的值), 那就把B的值(11)写入内存, 如果不相等(就是说过去的一段时间, 有人修改了内存value 的值), 意味着A已经不是最新值了, 那就放弃这次修改, 跳回第1步去”
我们面面相觑, 就这么简单? 真的没有加锁啊。
隔壁的小明反应最快: 小李子, 你这第三步有问题啊, 你看需要读内存吧,需要比较吧,还得写入内存吧, 这不是一个原子操作, 在我们多线程并发执行的时候, 肯定会出问题!
小李说: “唉, 说你们老土吧, 你们还不服气, 听说过comare and swap 这个硬件指令没有? 那个第三步其实就是一条硬件指令,保证原子执行。 在单个CPU上就不用说了,如果是有多个CPU, 这个指令甚至会锁住总线, 确保同一时刻只有一个CPU能访问内存!
这样吧, 干脆写成个指令: compareAndSwap(内存的值, A , B) , 这下子明白了吧? 还不明白? 估计是人类的语言你们听起来不太明白, 来吧,给你们来点熟悉的代码:”