V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
nonoName
V2EX  ›  Java

关于一个线程锁的问题

  •  
  •   nonoName · 2020-05-12 23:25:47 +08:00 via Android · 2210 次点击
    这是一个创建于 1654 天前的主题,其中的信息可能已经有所发展或是发生改变。
    今天面试的时候遇到一个问题

    java 重入锁,什么时候会出现后申请锁的线程,先获得锁的情况,什么原因导致的呢

    找了很多文章都没有找到理想的答案

    求助各位大佬
    6 条回复    2020-05-13 16:02:48 +08:00
    DarrenLuo
        1
    DarrenLuo  
       2020-05-12 23:33:29 +08:00 via Android
    可重入锁默认为非公平锁,在等待队列中的第一个线程在唤醒的过程中,需要比较大的资源开销,如果在这个开销期间有新的线程进来,则新线程直接进入执行
    cs419
        2
    cs419  
       2020-05-12 23:47:16 +08:00
    你写个方法 加上 synchronized
    然后递归调用自己 就相当于 反复获取锁

    synchronized 是可重入锁 , 所以能正常执行
    但如果你用的是不可重入锁, 那就会出现死锁

    [出现后申请锁的线程] 你这个说法 是多线程抢占锁 不适用于 可重入锁

    某一个锁(synchronized 、ReentrantLock 等) 可以有多种属性 (公平、重入、自旋等)
    就好像 person 的多种属性 name sex
    可重入锁 这个属性描述的就是某一线程下 重复获取锁的情况
    Jacky23333
        3
    Jacky23333  
       2020-05-12 23:58:49 +08:00 via Android
    可重入锁?你说的是 ReentrantLock 吗,reentrantLock 默认是非公平锁,底层是 aqs 进行实现的,非公平锁在获取锁的时候会先尝试用 cas 的方式去竞争锁(1),如果竞争锁失败的话才会把它加入到同步队列里面去,同步队列里面只有队头节点才能够持有锁,所以加入到队列里面的每一个节点都会一直循环去检查自己的前驱节点是不是头节点,如果是的话那么就会同样采用 cas 的方式去竞争锁(2),竞争成功了,就会把自己升级为头节点。那么就可能存在某一时,线程 a 处于 1 阶段,线程 b 处于 2 阶段,两个线程同时使用 cas 竞争锁,如果线程 a 成功了,那就会出现你说的,后申请的线程先竞争到锁的情况。
    freebird1994
        4
    freebird1994  
       2020-05-13 10:14:27 +08:00
    3l 正解
    nonoName
        5
    nonoName  
    OP
       2020-05-13 11:29:47 +08:00
    @DarrenLuo
    @cs419
    @Jacky23333

    谢谢解答,明白了
    jinzhongyuan
        6
    jinzhongyuan  
       2020-05-13 16:02:48 +08:00
    @Jacky23333 赞!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3596 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 00:53 · PVG 08:53 · LAX 16:53 · JFK 19:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.