Как определить, что несколько потоков вызывают функцию одновременно в C? - PullRequest
0 голосов
/ 21 мая 2019

Я хочу определить, можно ли вызывать определенную функцию в C из нескольких потоков одновременно, чтобы понять, нужно ли мне защищать ее мьютексами.Файл, в котором реализована и определена функция, не имеет механизма мьютекса, поэтому есть вероятность, что только один поток когда-либо получит доступ к функции, но есть вероятность, что несколько потоков сделают это.

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

Это мой код:

#include <stdio.h>

static __thread int threadCounter = 0;

void f(void)
{
    threadCounter++;

    // do something

    threadCounter--;
    printf("threadCounter: %d\n", threadCounter);
}

Мне интересно, если это решениедостаточно, чтобы определить, имеют ли несколько потоков доступ к функции, и есть ли лучшие способы сделать это.

Ответы [ 3 ]

2 голосов
/ 21 мая 2019

Из документации GCC : «Локальное хранилище потоков (TLS) - это механизм, с помощью которого переменные распределяются так, что для каждого существующего потока существует один экземпляр переменной».
Таким образом, ваше решение всегда будет указывать, что только один поток обращается к вашей функции одновременно, даже если это не так. Вы должны использовать переменную, которая является общей для потока. Но использование энергозависимого по-прежнему не является хорошим решением, потому что, если к нему одновременно обращаются несколько потоков, это значение может быть не лучшим.

В заключение, я думаю, что лучший способ сделать это - настроить мьютекс и использовать функцию pthread_mutex_trylock, чтобы определить, есть ли несколько потоков, пытающихся вызвать вашу функцию.

2 голосов
/ 21 мая 2019

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

1 голос
/ 21 мая 2019

Этот тест либо использует локальную переменную, либо сам по себе не является поточно-ориентированным.В любом случае, это не будет полезно в качестве доказательства.Если вы хотите использовать счетчик, вы должны защитить его чем-то вроде мьютекса или критической секции.Этого практически нет.

Но есть и другой способ сделать это лучше, предоставив вам точную информацию о том, кто вызвал функцию, и в то же время не нужно изменять реальную функцию.Вы можете создать «фиктивную» функцию:

#define f() ( print(__func__), f() )

. Она печатает имя функции обратного вызова потока, затем вызывает фактическую функцию f().Это работает, потому что токен препроцессора f() вычисляется перед любым вызовом функции.

Я написал функцию как пользовательскую print, так как у вас все еще будет проблема с несколькими потоками, пытающимися получить доступstdout сразу, если вы используете printf и т. д. Поэтому пользовательская функция print должна содержать средства обеспечения безопасности потоков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...