采纳答案成功!
向帮助你的同学说点啥吧!感谢那些助人为乐的人
老师,关于StampedLock有几个问题麻烦您解答: 1、是不是只有在写锁未被占用时才能获取乐观读锁?在悲观读锁被占用是也可以获取乐观读锁?而在其他线程占用乐观读锁的情况下可以获取写锁或悲观读锁? 2、当有线程获取写锁时,其他线程请求写锁会被阻塞,加入Wnode的队列,此时如果有其他线程请求悲观读锁,如图,它是Wnode节点还是cowait节点
你好,
1、以下是关于StampedLock涉及到锁的标准说明:
写锁writeLock,是个排它锁或者叫独占锁,同时只有一个线程可以获取该锁,当一个线程获取该锁后,其它请求的线程必须等待,当目前没有线程持有读锁或者写锁的时候才可以获取到该锁,请求该锁成功后会返回一个stamp票据变量用来表示该锁的版本,当释放该锁时候需要unlockWrite并传递参数stamp。
悲观读锁readLock,是个共享锁,在没有线程获取独占写锁的情况下,同时多个线程可以获取该锁,如果已经有线程持有写锁,其他线程请求获取该读锁会被阻塞。这里讲的悲观其实是参考数据库中的乐观悲观锁的,这里说的悲观是说在具体操作数据前悲观的认为其他线程可能要对自己操作的数据进行修改,所以需要先对数据加锁,这是在读少写多的情况下的一种考虑,请求该锁成功后会返回一个stamp票据变量用来表示该锁的版本,当释放该锁时候需要unlockRead并传递参数stamp
乐观读锁tryOptimisticRead,是相对于悲观锁来说的,在操作数据前并没有通过CAS设置锁的状态,如果当前没有线程持有写锁,则简单的返回一个非0的stamp版本信息,获取该stamp后在具体操作数据前还需要调用validate验证下该stamp是否已经不可用,也就是看当调用tryOptimisticRead返回stamp后到到当前时间间是否有其他线程持有了写锁,如果是那么validate会返回0,否者就可以使用该stamp版本的锁对数据进行操作。由于tryOptimisticRead并没有使用CAS设置锁状态所以不需要显示的释放该锁。该锁的一个特点是适用于读多写少的场景,因为获取读锁只是使用与或操作进行检验,不涉及CAS操作,所以效率会高很多,但是同时由于没有使用真正的锁,在保证数据一致性上需要拷贝一份要操作的变量到方法栈,并且在操作数据时候可能其他写线程已经修改了数据,而我们操作的是方法栈里面的数据,也就是一个快照,所以最多返回的不是最新的数据,但是一致性还是得到保障的
2、感觉你学的很深入,但问的问题又特别的基础(没有这些基础根本无法理解源码),有点看不出你到底学的是很深入还是很表面,cowait是专门用于链接等待读的线程队列
祝你学习愉快~
老师,首先很感谢您花费时间来回答我的问题,其实您的回答我已经在学习别人的研究源码的文章里看到过了,有的时候问的很基础的问题是希望您给个确认,比如第一个问题,我看的文章只有写到"如果当前没有线程持有写锁时才能获取乐观读锁",没有提到"如果当前有线程持有悲观读锁时,能不能获取乐观读锁"或者"如果当前有线程持有乐观读锁时,能不能获取悲观读锁"我有了自己的理解,但想得到您的确认就发上来了。 关于第二个问题,我也有看到"cowait是专门用来链接。。。"但除此之外没有具体的解释,有点不太明白具体过程,就像节点在condition队列和AQS队列之间移动那样的详细过程。 再次谢谢老师这么晚还在看问题!
我感觉你想问我源码细节,但提的问题又不是根据代码来的,我感觉直接回答是否看起来很敷衍,而且对你实际也不一定有用,就只能选择以标准的解释说一遍了。 另外,我不知道你这些源码和架构图是从哪里来的,如果你认为他有问题还去看我感觉这样学起来就太累了,要么你就信任他说的,要么就用源码或自己写代码来验证他是错的,连他说的基础内容你也质疑的话,那你学习起来感觉会很吃力,基本他说什么你都要想到底对还是不对了。
我没有质疑他说的,我问的都是他没有提到的(第一个问题的部分)或没有详细解释的(第二个问题),我想让您确认的也只是我看完他写的东西之后的我自己的想法。
登录后可查看更多问答,登录/注册
构建完整并发与高并发知识体系,倍增高薪面试成功率!
1.7k 1
1.1k 18
1.1k 15
3.5k 12
1.2k 12