Skip to content

lock basic_lock

wangkaiwu edited this page Feb 14, 2022 · 2 revisions

synchronize Lock

Monitor Enter

尝试轻量锁

void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, JavaThread* current) {
    markWord mark = obj->mark();
    // 是否无锁
    if (mark.is_neutral()) {
        // lock 在线程栈上分配,此步骤是记录对象的 markword 到 lock 对象中。
        lock->set_displaced_header(mark);
        // 尝试将对象从无锁变为轻量锁
        if (mark == obj()->cas_set_mark(markWord::from_pointer(lock), mark)) {
            return;
        }
    } else if (mark.has_locker() && current->is_lock_owned((address)mark.locker())) {
        // 如果已经被轻量级锁锁定,且 markword 指向的栈地址位于本线程的栈空间
        // 则相当于锁重入,此时只需要将当前栈帧的 lock 对象的 displaced_header 置为无效
        lock->set_displaced_header(markWord::from_pointer(NULL));
        return;
    }
    // 将 displaced_header 置为无效
    lock->set_displaced_header(markWord::unused_mark());
    while (true) {
        // 膨胀为重量级锁
        ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_monitor_enter);
        if (monitor->enter(current)) {
            return;
        }
    }
}

锁膨胀

ObjectMonitor* ObjectSynchronizer::inflate(Thread* current, oop object, const InflateCause cause) {
    EventJavaMonitorInflate event;
    for (;;) {
        // 对象的 markword
        const markWord mark = object->mark(); 
        // 是否已经是重量锁了
        if (mark.has_monitor()) {
            ObjectMonitor* inf = mark.monitor();
            // 返回 monitor 指针
            return inf;
        }
        // markWord::INFLATING() == 0,判断是否在膨胀中
        if (mark == markWord::INFLATING()) {
            //TODO:
            read_stable_mark(object);
            continue;
        }
        // 是否是轻量锁
        if (mark.has_locker()) {
            // 创建 monitor 对象
            ObjectMonitor* m = new ObjectMonitor(object);
            // 修改被锁对象为膨胀中的状态 
            markWord cmp = object->cas_set_mark(markWord::INFLATING(), mark);
            // 判断是否cas操作成功
            if (cmp != mark) {
                // 操作失败,重试
                delete m;
                continue;       // Interference -- just retry
            }
            // 轻量锁生效时,对象 markword 中存储的是 lock record 的地址
            // lock record 对应的是持有锁线程的栈空间里的一个对象
            // 下面方法可以从 lock record 中取到锁对象原来的mark word
            markWord dmw = mark.displaced_mark_helper();
            // 在 monitor 中存储 mark word
            m->set_header(dmw);
            // 设置锁当前被哪个线程持有
            m->set_owner_from(NULL, mark.locker());
            // 由于升级为重量级锁,所以对象头存储的 mark word 需要改为 monitor 的地址
            object->release_set_mark(markWord::encode(m));
            // 添加到使用列表中
            _in_use_list.add(m);
            // 发出膨胀事件
            if (event.should_commit()) {
                post_monitor_inflate_event(&event, object, cause);
            }
            return m;
        }
        // 当前已经处于重量锁中,尝试一下能否获取到锁
        ObjectMonitor* m = new ObjectMonitor(object);
        // 在 monitor 中记录 mark word
        m->set_header(mark);
        // 尝试将对象的mark word 设置为 monitor 对象的地址
        if (object->cas_set_mark(markWord::encode(m), mark) != mark) {
            // 修改失败,删除对象
            delete m;
            m = NULL;
            continue;
        }
        // 升级为膨胀锁
        _in_use_list.add(m);
        // 发出膨胀事件
        if (event.should_commit()) {
            post_monitor_inflate_event(&event, object, cause);
        }
        return m;
    }
}

monitor 进入

bool ObjectMonitor::enter(JavaThread* current) {
    // 尝试占有锁
    void* cur = try_set_owner_from(NULL, current);
    if (cur == NULL) {
        // 抢占成功
        return true;
    }
    // 判定是否锁重入
    if (cur == current) {
        // 记录重入次数
        _recursions++;
        // 锁重入
        return true;
    }
    // TODO: 不太理解,表层意思就是比较占有锁的线程是否是当前线程
    if (current->is_lock_owned((address)cur)) {
        _recursions = 1;
        set_owner_from_BasicLock(cur, current);  // Convert from BasicLock* to Thread*.
        return true;
    }
    // 设置当前线程的 _Stalled 为当前 monitor 的地址
    current->_Stalled = intptr_t(this);
    // 尝试自旋获取锁
    if (TrySpin(current) > 0) {
        current->_Stalled = 0;
        return true;
    }
    add_to_contentions(1);
    if (is_being_async_deflated()) {
        const oop l_object = object();
        if (l_object != NULL) {
          install_displaced_markword_in_object(l_object);
        }
        current->_Stalled = 0;
        add_to_contentions(-1);
        return false;
    }
    EventJavaMonitorEnter event;
    if (event.is_started()) {
        event.set_monitorClass(object()->klass());
        event.set_address((uintptr_t)this);
    }
    {
        JavaThreadBlockedOnMonitorEnterState jtbmes(current, this);
        current->set_current_pending_monitor(this);
        OSThreadContendState osts(current->osthread());
        for (;;) {
            ExitOnSuspend eos(this);
            {
                ThreadBlockInVMPreprocess<ExitOnSuspend> tbivs(current, eos);
                EnterI(current);
                current->set_current_pending_monitor(NULL);
            }
            if (!eos.exited()) {
                break;
            }
        }
    }
    add_to_contentions(-1);
    current->_Stalled = 0;
    if (event.should_commit()) {
        event.set_previousOwner((uintptr_t)_previous_owner_tid);
        event.commit();
    }
    return true;
}

Clone this wiki locally