#c #multithreading
#c #многопоточность
Вопрос:
У меня есть функция C , которая вызывается фреймворком, к коду которого у меня нет доступа. Если фреймворк вызывает этот код из нескольких потоков, мне нужно разместить блокировки мьютекса в нескольких местах. Если это не так, я не хочу, чтобы мьютексы снижали производительность. Учитывая, что я могу запускать код через фреймворк, есть ли способ определить, вызывает ли фреймворк функцию из нескольких потоков?
Комментарии:
1. Лично я бы просто вставил небольшой отладочный код и записал все идентификаторы потоков в файл (с мьютексом на месте, конечно). На самом деле, это не так. Я бы вставил мьютекс и беспокоился, когда кто-то сказал мне, что код слишком медленный.
Ответ №1:
Если у вас c 11, вы можете использовать std::this_thread::get_id()
и сохранять / регистрировать это значение при каждом вызове функции. Например.,
void my_func()
{
std::cout << "my_func called from thread " << std::this_thread::get_id() << std::endl;
...
}
Комментарии:
1. И если C 11 недоступен, у каждой ОС есть собственная функция для получения идентификатора потока.
2. В общем случае это не работает, thread_id может быть переработан и использоваться новыми потоками.
3. @quantdev в рамках одного процесса? Я ожидаю, что это теоретическая возможность, и ее стоит отметить, так что спасибо, но не практическая возможность. Я годами использовал описанную выше технику только для того, чтобы отлаживать OP, и никогда не был введен в заблуждение. Наихудший сценарий: запустите программу еще раз, молния, вероятно, не ударит дважды.
4. Даже если она была переработана, это можно было сделать только после завершения первого потока. Вы бы говорили о последовательных потоках. Для указанной цели (определить, используется ли несколько одновременных потоков) достаточно распечатать идентификатор, поскольку идентификаторы уникальны в любой момент.
5. Я не думаю, что этого достаточно для обнаружения одновременного доступа к функции, о чем и спрашивает OP. Он покажет, какие потоки вызвали функцию, но доступ может быть последовательным, а не одновременным.
Ответ №2:
Комментарий капитана Очевидного очень важен: RTFM. Если вы не можете найти инструкцию в документе, вы можете либо использовать std::this_thread::get_id()
, как указано Мэттом, либо, если вы не хотите редактировать какой-либо код, используйте отладчик!
Просто установите точку останова для символа, соответствующего интересующей вас рамочной функции, и запустите свою программу. Приличный отладчик может даже принимать регулярные выражения для создания нескольких точек останова одной командой. Когда программа остановится, просто посмотрите на идентификатор потока, и вы узнаете, есть ли у вас критический раздел или нет.
Вот lldb и gdb способы установки точек останова с помощью регулярного выражения:
(lldb) breakpoint set --func-regex regular-expression
(gdb) rbreak regular-expression