• Liam
    2019-06-18
    StampLock不支持重入,不支持条件变量,线程被中断时可能导致CPU暴涨

    作者回复: 回答很全面

     1
     18
  • KingSwim
    2019-07-04
    重复是学习最好的方式——没有之一。虽然好几个Java专栏都会讲到锁的问题。但是,每次看完都是只能懂一部分。但是,每看完一个专栏就清晰一点,只有不断的重复,才能掌握好一个知识点。感觉复习同一个也会有效果(部分专栏看过 2 边,感觉有点耽误时间,专栏太多)。但是还是不如看新的专栏,因为同时还有其他知识点的收获。现在对温故而知新的”故“有了新的理解。另外,老师的 lock 是我看过专栏里面讲得最清晰的。
    
     8
  • -W.LI-
    2019-06-18
    老师好!读写锁那个流程图看不太明白,没有写线程的时候,判断不是当前线程在读就会进入CLF阻塞等待。
    问题1:不是可以并发读的嘛?按这图读线程也要阻塞等待的意思么?
    问题二:CLF阻塞队列里是读写线程公用的么?队列里,读写交替出现。那不就没法并发读了么?

    作者回复: 第一个问题,这里有一个公平锁和非公平锁的情况,如果是公平锁,即使无锁竞争的情况下,也会进入阻塞队列中排队获取锁;否则,会立即CAS获取到读锁。

    第二个问题,是公用的,这里同样涉及到了公平锁和非公平锁,读写线程对于程序来说都是一样的。如果是非公平锁,如果没有锁竞争的情况下CAS获取锁成功,是无需进入阻塞队列。如果是公平锁,都会进入阻塞队列。

    
     8
  • 英长
    2019-06-19
    希望老师能多结合实践讲讲应用场景
    
     4
  • 密码123456
    2019-06-18
    为什么?因为锁不可重入?

    作者回复: 是的,StampedLock不支持可重入。如果在一些需要重入的代码中使用StampedLock,会导致死锁、饿死等情况出现。

    
     3
  • 我知道了嗯
    2019-06-20
    可重入锁是什么?另外什么场景下会使用到?

    作者回复: 可重入锁是指在同一个线程在前面方法中已获取锁了,再进入该线程的其他方法获取锁,此时不会因为之前获取锁而阻塞。
    平时我们很少遇到这种情况,例如在A方法中使用了对象锁,B方法中也使用了该对象锁,平时一般都是分别调用A方法和B方法,而后面由于业务需求刚好需要在A方法中调用B方法,此时就会需要锁支持可重入性。

    
     2
  • 趙衍
    2019-06-19
    谢谢老师的回复!关于StampedLock,我的理解是乐观读的时候,线程把stamp的值读出来,通过与运算来判断当前是否存在写操作。这个过程是不涉及CAS操作的。可是如果有线程需要修改当前的资源,要加写锁,那么就需要使用CAS操作修改stamp的值。不知道这样理解是否准确。
    此外,前排@-W.LI-同学提出的那个问题,并发读的时候也需要按照是否是公平锁进入CLH队列进行阻塞我还不是很明白,既然大家都是读操作,互相之间没有冲突,我每个线程都直接用CAS操作获取锁不就行了吗,为什么还要进队列阻塞等待呢?
    
     2
  • QQ怪
    2019-06-18
    老师这篇干货很多,看了2~3遍,大体理解了底层AQS锁原理,期待老师多多分享更多相关的文章
    
     2
  • -W.LI-
    2019-06-18
    StampedLock在写多读少的时候性能会很差吧

    作者回复: 是的,写多读少的性能没有优势。

    
     2
  • 趙衍
    2019-06-18
    老师我有几个问题:
    1.在ReentrantLock中,state这个变量,为0的时候表示当前的锁是没有被占用的。这个时候线程应该用CAS尝试修改state变量的值对锁进行抢占才对呀,为什么在您的图里当state=0的时候还需要判断是否为当前线程呢?
    2.老师提到读写锁在读多写少的情况下会使得写线程遭遇饥饿问题,那我是不是只需要将锁设置为公平锁,这样先申请写锁的线程就可以先获得锁,从而避免饥饿问题呢?
    3.StampedLock中引入了一个stamp版本对版本进行控制,那么对这个stamp变量进行写入的时候是否需要使用CAS操作?如果不是,那如何保证对stamp变量的读写是线程安全的呢?
    谢谢老师!
    展开

    作者回复: 第一个问题,是老师笔误,搞错方向了,现在已更正。

    第二个问题,如果读多写少的情况下,即使是公平锁,也是需要长时间等待,不是想获取时就能立即获取到锁。StampedLock如果是处于乐观读时,写锁是可以随时获取到锁。

    第三个问题,StampedLock源码中存在大量compareAndSwapObject操作来保证原子性。

    
     1
  • QQ怪
    2019-06-18
    刚想反馈图片一个字母写反了,刷新一下,立马被修复了,厉害厉害,佩服老师的效率
    
     1
  • 张学磊
    2019-06-18
    老师,tryOptimisticRead操作获取的不应该叫乐观读锁,应该是乐观读,是无锁的;StampedLock名字中没有Reentrant,所以不支持重入;StampedLock也不支持条件变量。

    作者回复: 这就是一种按版本号实现的读乐观锁,我们经常会在数据库更新操作时用到这种基于版本号实现的写乐观锁。

    对的,StampedLock不支持重入。

    
     1
  • 。。。。。
    2020-01-10
    老师,请问一下,
    问题一:那两个流程图,为什么同样是判断state低16位是否为0,为否时,一次是判断获取写锁的线程是否为当前线程,一次是判断获取读锁的线程是否为当前线程
    问题二:当中间某一步就可以知道锁获取失败(比如获取读锁流程中,state低16位不为0,且获取写锁的不是当前线程),不是就直接可以放入队列了吗,为什么还要判断是否为公平锁
    
    
  • 王圣军
    2019-12-27
    老师这里说的公平锁和非公平锁让我想起两者是获取方式不同,非公平锁是首先就CAS来获取一次,成功就拿到锁,失败就放入队列;公平锁不会有这步操作,直接放入队列

    作者回复: 是的

    
    
  • 奋斗的小白鼠
    2019-11-28
    老师,lock锁中的线程阻塞进行的上下文切换会设计系统内核态和用户态的转换吗?啥时候会引起系统内核态和用户态转换成啊?.io流编程中会出现吗

    作者回复: lock锁阻塞不会带来进程间的上下文切换,IO流存在的,在09讲中讲到了

    
    
  • 又双叒叕是一年啊
    2019-11-10
    RRW 加写锁 和 读锁 都需要判断低16位? 这块写锁是不是应该判读的是高16位有没有读锁,从而判断有没有冲突?

    作者回复: 从源码分析,都会进行高低位的判断,获取写锁时,如果state!=0 and w==0,就可以判断了此锁r!=0,也就是判断了高16位有没有读锁了。

    
    
  • 又双叒叕是一年啊
    2019-11-10
    请教下,非公平锁是怎么玩的随机唤醒一个等待线程Node节点的,是压根不考虑CLH队列的顺序吗? 还是非公平锁压根不把获取锁失败的线程封装成Node加入到CLH队列中?
     1
    
  • 赤城
    2019-11-08
    老师,公平锁因为要维持一个线程执行的顺序,是不是性能相对非公平锁弱一些?

    作者回复: 一般占有锁时间非常短,队列的长度也不会太长,这个性能几乎可以忽略

    
    
  • godtrue
    2019-09-09
    课后思考及问题
    1:公平锁和非公平锁具体指什么?怎么体现?

    2:锁的状态可中断和不可中断具体是指什么意思?

    晚上加班状态可能不太好,感觉老师主要讲解了几种同步锁的实现原理,以及特点,如果能列个二维表就更好啦!
    展开

    作者回复: 我们进入到底层代码,可以发现其实公平锁和非公平锁的区别就是是否进入队列,公平锁是会进入到队列中排队等待唤醒,而非公平锁则是直接CAS获取锁。

    Lock锁如果监测到中断就直接throw new InterruptedException();抛出来了,所以可以响应中断。

    具体可参考源码。


    
    
  • 风轻扬
    2019-08-24
    老师,隐式锁只有synchronized这一种吗?

    作者回复: 对的

    
    
我们在线,来聊聊吧