Перейти к содержанию

Последнее обновление:2026-10-12

Обнаружение ошибок конкурентности с помощью Helgrind

C++那些事: обнаружение проблем параллельного программирования с помощью helgrind

При написании многопоточных программ мы обычно легко сталкиваемся с двумя проблемами:

  • возник дедлок, а причина непонятна
  • несогласованность данных — несколько потоков неправильно используют блокировки

Есть ли инструмент для обнаружения этих двух сценариев?

Ответ — да: можно использовать инструмент helgrind из valgrind. Чтобы изложение в этой статье было более плавным, приведу несколько примеров.

Примечание: полные примеры и исправленные версии уже выложены в закрытом сообществе.

Взаимоблокировка

Предположим, два потока удерживают блокировки друг друга — так мы можем смоделировать дедлок, например:

void thread_func1() {
    std::lock_guard<std::mutex> lock1(mutex1);
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    std::lock_guard<std::mutex> lock2(mutex2);
}

void thread_func2() {
    std::lock_guard<std::mutex> lock2(mutex2);
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    std::lock_guard<std::mutex> lock1(mutex1);
}
Способ использования helgrind следующий:

valgrind --tool=helgrind ./a.out 
Теперь мы видим место взаимоблокировки; например, в этом примере указано, в каких точках двух потоков произошёл дедлок

thread_func2() (deadlock.cc:18)
thread_func1() (deadlock.cc:12)
deadlock

Гонка данных

Предположим, есть разделяемая переменная, которую мы в нескольких потоках увеличиваем 100 тысяч раз — каким будет результат?

Очевидно, здесь возникает проблема конкуренции нескольких потоков за глобальную переменную: итоговый результат оказывается некорректным. Способ обнаружения с помощью helgrind тот же, что и выше.

int shared_var = 0; 

void increment() {
    for (int i = 0; i < 100000; ++i) {
        ++shared_var; 
    }
}
Теперь мы можем увидеть, на какой строке происходит data race, и затем устранить проблему.

datarace

Напоследок оставлю несколько вопросов:

1.Как исправить эти два проблемных фрагмента кода?

2.Кроме описанного выше инструмента, есть ли другие способы?

Конец раздела

Похожие темы

Комментарии