Jameopl 2022-07-11 20:40
浏览 11
已结题

ReentrantLock的unlock方法,将head节点状态设置为0的作用是啥?

在java的ReentrantLock 的unlock()->release()->unparkSuccessor()方法中

private void unparkSuccessor(Node node) {
    int ws = node.waitStatus;
    if (ws < 0)
        compareAndSetWaitStatus(node, ws, 0);
    //................
}

关于compareAndSetWaitStatus这段的作用是什么呢? 我研究了下

假设AB两线程,A线程先执行,准备走unlock时切换到B,B线程第一次执行到lock() ->acquire()->acquireQueued()->shouldParkAfterFailedAcquire()方法时

private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
    int ws = pred.waitStatus;
    if (ws == Node.SIGNAL)
        return true;
    if (ws > 0) {
        do {
            node.prev = pred = pred.prev;
        } while (pred.waitStatus > 0);
        pred.next = node;
    } else {
        compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
    }
    return false;
}

compareAndSetWaitStatus(pred, ws, Node.SIGNAL);当B线程走过到else代码块后,时间片用完此时head节点状态为-1

然后回到A线程执行unlock()->release()->unparkSuccessor()

private void unparkSuccessor(Node node) {

    int ws = node.waitStatus;
    if (ws < 0)
        compareAndSetWaitStatus(node, ws, 0);
    
    Node s = node.next;
    if (s == null || s.waitStatus > 0) {
        s = null;
        for (Node t = tail; t != null && t != node; t = t.prev)
            if (t.waitStatus <= 0)
                s = t;
    }
    if (s != null)
        LockSupport.unpark(s.thread);
}

释放了锁,然后将head节点的状态改为了0,然后回到B线程

final boolean acquireQueued(final Node node, int arg) {
    boolean failed = true;
    try {
        boolean interrupted = false;
        for (;;) {
            final Node p = node.predecessor();
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null; // help GC
                failed = false;
                return interrupted;
            }
            
           //B线程执行完方法后返回到这里
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                interrupted = true;
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

那么B线程继续for循环,之后就获取到了锁,并置空了head节点,所以A线程在unlock()中修改的head状态并没有什么作用

不是太明白这个步骤,而且注释上写了是允许这个cas失败的,这点也不是太明白

  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 7月19日
    • 创建了问题 7月11日

    悬赏问题

    • ¥15 stm32代码移植没反应
    • ¥15 matlab基于pde算法图像修复,为什么只能对示例图像有效
    • ¥100 连续两帧图像高速减法
    • ¥15 组策略中的计算机配置策略无法下发
    • ¥15 如何绘制动力学系统的相图
    • ¥15 对接wps接口实现获取元数据
    • ¥20 给自己本科IT专业毕业的妹m找个实习工作
    • ¥15 用友U8:向一个无法连接的网络尝试了一个套接字操作,如何解决?
    • ¥30 我的代码按理说完成了模型的搭建、训练、验证测试等工作(标签-网络|关键词-变化检测)
    • ¥50 mac mini外接显示器 画质字体模糊