4

我有被 tsan 识别为锁顺序反转的代码。这是一个误报。我知道我可以使用抑制文件来防止这种情况,但我想知道我是否可以对我的代码做一些事情,以便我的意图更清晰并且不会被错误识别。这就是我正在做的事情:

void addObject(ObjectData objectData) {
    unique_lock listLock(listMutex);
    ObjectPtr obj = list.createObject(objectData);
    // we need to lock the object here because it's created but not finalized
    // finalization can take time and we don't want to keep the list locked 
    // during that time so that other objects can be added or gotten
    obj->mutex.lock();
    listLock.unlock();

    obj->finalize();
    obj->mutex.unlock();    
}

void cloneObject(ObjectName name) {
    shared_lock listLock(listMutex);
    auto obj = list.getObjectByName(name);
    listLock.unlock();

    // will wait here if object is not finalized
    unique_lock objLock(obj->mutex);
    addObject(obj->data());
}

这是 tsan 观察到的:

threadA => addObject => list.lock success
threadA => addObject => objX.lock success LIST IS LOCKED
threadA => addObject => list.unlock
// and later:
threadB => cloneObject => objX.lock success
threadB => cloneObject => addObject => list.lock success OBJX IS LOCKED

这是它警告我可能发生的事情:

threadA => addObject => list.lock success
threadB => cloneObject => objX.lock success
threadA => addObject => objX.lock waiting
threadB => cloneObject => addObject => list.lock DEAD LOCK

问题是这不可能发生,因为 addObject 获取对象锁的唯一时间是如果对象刚刚创建并且无法成功锁定对象,这可能导致同一对象被锁定addObject。调用addObjectfromcloneObject将产生一个对象锁,但这必然是另一个对象,而不是被克隆的对象。

4

0 回答 0