У меня есть код, который Цан идентифицирует как инверсию порядка блокировки. Это ложный позитив. Я знаю, что могу использовать файлы подавления, чтобы предотвратить это, но мне интересно, могу ли я что-то сделать с моим кодом, чтобы мое намерение было более ясным и не было ошибочно идентифицировано. Вот что я делаю:
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());
}
Вот что заметил цан:
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
из cloneObject
приведет к блокировке объекта, но это обязательно будет другой объект, а не тот, который клонируется.