Блокировка слишком длинная

У меня есть приложение, в котором несколько потоков используют мьютекс.

std::lock_guard< std::recursive_mutex > lock(globalMutex_);

Один интенсивно (T1) остальные меньше (T2,T3 ..).
У меня есть пример, в котором потоки, которые требуют блокировки, реже блокируются за 100 секунд до успешного получения блокировки.

Протектор (T1 итак) которые приобретают блокировку часто делают это следующим образом:

void func()
{
std::lock_guard< std::recursive_mutex > lock(globalMutex_);
processing();
}

globalMutex_тогда хорошо выпускается периодически.

Странное поведение:

T1 получить блокировку систематически в течение 100 секунд, в то время как другой поток вообще не получает блокировку

(В других потоках у меня тот же шаблон, но другой функционал вызывается реже)

Вопрос:
Чем это можно объяснить? Это нормальное поведение?

Контекст:
Я нахожусь под Windows 10 / последняя версия Visual Studio / 64 бит / GUI приложения

Замечания:
Даже если я положу T2 с высоким приоритетом ситуация такая же.

0

Решение

std::mutex не дает никаких гарантий, что мьютексы заблокированы в том порядке, в котором их вызывают lock(), Когда поток снимает блокировку, если поток быстро блокирует блокировку, тогда, если другой поток уже не ожидает блокировки и не выполняет в то же время, первый поток, вероятно, преуспеет в восстановлении блокировки.

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

Более сложным решением является создание собственного класса мьютекса, который обеспечивает некоторые гарантии порядка блокировки / разблокировки. Вы можете реализовать это с помощью комбинации std::mutex а также std::condition_variable,

2

Другие решения

Это выглядит как ошибка:

{
std::lock_guard< std::recursive_mutex > lock(globalMutex_);
processing();
}

Что значит processing() делать? Если это занимает более нескольких микросекунд, то, вероятно, есть более эффективный способ решения вашей проблемы. Иногда это выглядит так:

bool success=false;
while (! success) {
auto result = speculative_processing();
{
std::lock_guard< std::recursive_mutex > lock(globalMutex_);
success = attempt_to_publish(result);
}
}

Часто бывает так, что отдельным потокам в многопоточной программе приходится выполнять дополнительную работу, чтобы не мешать друг другу. Но, стараясь не мешать друг другу, они могут лучше использовать несколько процессоров, и они быстрее справляются с работой.

1

По вопросам рекламы [email protected]