我有被 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
。调用addObject
fromcloneObject
将产生一个对象锁,但这必然是另一个对象,而不是被克隆的对象。