第三次读到这一节,才弄懂了乐观锁与悲观锁对读写影响的区别。
Topic source当然不对了
一般来说写锁的优先级要高于读锁,read-write-lock假定读很多几乎不会间断,如果突然来个写锁,那么只需等当前正在读的释放读锁后,写就立刻获得写锁,其它后续读都得等,不然你想,在一直都有读的情况下,永远写不了
1 楼说的对也不对,如果是公平的读写锁的确会有这样的问题,但是 Java 对于 ReadWriteLock 的读锁的抢锁的策略做了限制,当阻塞队列中第一个线程是一个写线程的时候,那读锁就不会参与抢锁,而是直接阻塞,这在一定程度上解决了写锁‘饿死’的问题,JDK8 中的 StampedLock 进一步解决了写锁被读锁阻塞的问题,在‘乐观锁’的读锁状态下,写锁可以直接进行获取锁,不用进行抢锁,而且 StampLock 对于抢锁失败阻塞造成频繁的上下文切换也进行了优化,线程在抢锁时(底层使用 CAS 实现)如果失败不会直接阻塞,而是通过‘自旋’不断尝试获取锁,直到尝试次数达到上限(单核CPU为0,多核为2^16)才会进行阻塞,等待被唤醒,唤醒后依旧进行自旋,如果依旧无法获得锁,那么再阻塞等待被唤醒。。。
- 1
SNH48-刘慈欣
前一节ReadWriteLock末尾,我一直在想,(使用悲观锁时)虽然写稀少而读频繁,读之间互不影响可以完全异步进行。但是写是需要等待读的,而读又是频繁的。例如假设一个论坛的贴子10分钟内,有10000次浏览(读)和一次回复(写),假设性能为10000次浏览需要10分钟才能进行完,那么这个回复操作需要和这10000个浏览操作一起排队,运气正常的情况下,很有可能要等8-10分钟才能开始写入操作(1/10001的机率,虽然每次分母减1,不存在优先级的情况下,cpu很快选到你也是一种幸运吧)。
而乐观锁,在读开始前实际没加锁,只是记录版本号,这意味着,无论多少读在同时进行,写都能直接开始,然后读结束时检查版本号,不一致则重新加锁并修正数据。这样一来,上面的例子就不会出现需要等待8-10分钟才能开始回复的写入操作了。
我觉得乐观锁就是为了解决上面这种情况而产生的,不知道我理解的对不对?