У меня есть рабочий поток, выполняющий опрос (он нацелен на libcurl, но это не имеет значения).
Многие действия из приложения могут запускать рабочий поток, но если он уже запущен, новый поток создавать не нужно. Новый запрос от приложения просто объединяется с любым другим уже проводящимся опросом.
В общем, один рабочий поток, который завершается, когда больше нечего делать.
Код:
pthread_t thread = NULL;
struct timespec sleep_val = {0, 20000000};
void *worker_thread(void *threadid)
{
do {
poll();
nanosleep(&sleep_val, NULL);
} while (no_of_handles_running > 0);
pthread_exit(NULL);
thread = NULL;
}
void start_worker_thread_if_needed() {
if (thread == NULL) {
pthread_create(&thread, NULL, worker_thread, NULL);
}
}
Я сомневаюсь в безопасности потоков. Функцию start_worker_thread_if_needed() можно вызывать в любое время любое количество раз.
Итак, что, если start_worker_thread_if_needed() вызывается именно тогда, когда мы выходим из цикла while, и тем самым прерывает рабочий поток. Если это произойдет, условие if (thread == NULL) будет FALSE, поскольку рабочий поток прерван, а pthread_exit + thread = NULL еще не завершен.
Итак, теперь start_worker_thread_if_needed() завершится без создания нового потока, но как только управление будет возвращено старому рабочему потоку, он перейдет к строке pthread_exit, и рабочий поток будет уничтожен.
Проблема будет заключаться в том, что только что сделанный запрос, запускающий start_worker_thread_if_needed(), будет потерян, и опрос не начнется до следующего вызова start_worker_thread_if_needed().
Изменить: вот предложение с мьютексом, но у меня все еще есть те же сомнения. Что произойдет, если основной поток прервется сразу после выхода из цикла while и до того, как рабочий сможет взять мьютекс? Затем основной поток не создает новый поток, а затем рабочий завершает работу.
void *worker_thread(void *threadid)
{
do {
poll();
nanosleep(&sleep_val, NULL);
} while (no_of_handles_running > 0);
pthread_mutex_lock(&my_mutex);
thread = NULL;
pthread_mutex_unlock(&my_mutex);
pthread_exit(NULL);
}
void start_worker_thread_if_needed() {
pthread_mutex_lock(&my_mutex);
if (thread == NULL) {
pthread_create(&thread, NULL, worker_thread, NULL);
}
pthread_mutex_unlock(&my_mutex);
}
Я думаю, что у меня есть недостаток в том, как я это настроил, и было бы очень признательно, если бы кто-нибудь мог помочь с правильным решением.
pthread_exit
, так как поток завершился, поэтому он не будет выполнять операциюthread = NULL;
. - person David Schwartz   schedule 18.02.2016thread
обращаются несколько потоков, вам необходимо должным образом защитить доступ к ней. Наиболее распространенный метод - с мьютексом. Подробнее см.pthread_mutex_lock
иpthread_mutex_unlock
. - person kaylum   schedule 18.02.2016pthread_exit
, на которую указал Дэвид, и игнорирование проблем с видимостью: представьте, что рабочий поток видитno_of_handles_running == 0
и поэтому выходит из цикла, а затем основной поток видит, что рабочий поток работает, поэтому он не запускает его, а затем рабочий поток завершается, не видя новой работы. - person user253751   schedule 18.02.2016thread
в любой момент времени. Части кода, которые обращаются к общему ресурсу, называются критическим разделом. Все критические секции должны быть защищены путем блокировки мьютекса перед CS и разблокировки после CS. - person kaylum   schedule 18.02.2016pthread_mutex_unlock
находится не в том месте вstart_worker_thread_if_needed
. Он должен идти после блокаif
(т. е. вы всегда должны разблокировать мьютекс). Кроме этого, он должен работать нормально. О, если, конечно, вы правильно инициализировалиmy_mutex
(это не показано). - person kaylum   schedule 18.02.2016no_of_handles_running
также является общей переменной, к которой могут обращаться несколько потоков, что означает, что она также должна быть защищена. Кроме того, как уже было сказано выше ... почему вы вообще выходите из рабочего потока? Почему бы просто не позволить ему периодически просыпаться для проведения опроса (или, что еще лучше, сигнализировать ему о пробуждении, когда нужно выполнить работу)? - person kaylum   schedule 18.02.2016poll
илиselect
. Если ваши требования шире, другой вариант — переменные условия — см.pthread_cond_wait
иpthread_cond_signal
. - person kaylum   schedule 18.02.2016