Я создал несколько потоков и хочу запускать их с помощью циклического режима, используя переменную условия и сигнал (pthread_cond_wait & pthread_cond_signal).
Я использовал два подхода, один подход работает, но тратит процессор, тогда как другой подход не работает, не теряя процессор.
Проблема, с которой я столкнулся, - сигнал посылается до того, как мои потоки ожидают, и сигнал потерян. поэтому он переходит в бесконечный цикл ожидания.
Первый подход:
Темы создаются и ждут переменной условия и непрерывно проверяют переменную, называемую state (внутри цикла while).
когда state == my_id поток с my_id активирован, и затем он сигнализирует о следующем потоке my_id + 1 и так далее.
DRAWBACK: Очистка процессора
Второй подход:
Потоки создаются и ждут сигнала для его собственной переменной условия. Теперь, когда сигнал уже отправлен до начала запуска потока, сигнал теряется, и программа переходит в бесконечный цикл ожидания.
Есть ли что-то вроде "Self Signaling" или другим способом отправки сигнала, когда сигнал потерян?
Я использую g++ под linux. Любая подсказка будет высоко оценена. Заранее спасибо.
Программа с первым подходом здесь круглая.
Вот моя программа со вторым подходом:
#include <pthread.h>
#include <stdio.h>
#include <iostream>
#include <mutex> // std::mutex
#define MULTIPLE_THREADS 2
#define NTHREADS MULTIPLE_THREADS*64
#define NO_OF_LOOP 1
pthread_cond_t cond[NTHREADS];
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
using namespace std;
/* This is our thread function. It is like main(), but for a thread*/
void *threadA(void *arg)
{
long my_id = (long)arg;
int i = 0;
while(i < NO_OF_LOOP)
{
// Awaken or unblocked by thread (i-1)
pthread_mutex_lock(&mutex1);
pthread_cond_wait(&cond[my_id], &mutex1);
pthread_mutex_unlock(&mutex1);
printf("I am thread - %ld",my_id);
++i;
/* wake up thread i+1 */
pthread_mutex_lock(&mutex1);
pthread_cond_signal(&cond[(my_id + 1) % NTHREADS]);
pthread_mutex_unlock(&mutex1);
}
return NULL;
}
int main(void)
{
pthread_t threadid[NTHREADS];
// Initialization
for(int i=0;i<NTHREADS;i++)
cond[i]= PTHREAD_COND_INITIALIZER;
//printf("Create %d threads\n", NTHREADS);
for(long i=0; i<NTHREADS; ++i) {
pthread_create(&threadid[i], NULL, threadA, (void *)i);
//printf("Thread created=%d\n", i);
}
// printf("Wait for threads and cleanup\n");
for (long i=0; i<NTHREADS; ++i) {
pthread_join(threadid[i], NULL);
}
return 0;
}
Таким образом вы не можете использовать переменную условия. Вам всегда нужен предикат. То есть вам нужна переменная, которую вы можете проверить, произошло ли событие.
Простое выключение слепых pthread_cond_wait и pthread_cond_signal заставит вас потерять события. Там могут быть побочные пробуждения, и если поток, который вы сигнализируете, не заблокирован в pthread_cond_wait(), он пропустит событие (pthread_cond_signal() не стоит в очереди).
Вам понадобится нечто подобное (не проверено):
pthread_cond_t cond[NTHREADS];
int wakeup[NTHREADS];
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
using namespace std;
/* This is our thread function. It is like main(), but for a thread*/
void *threadA(void *arg)
{
long my_id = (long)arg;
int i = 0;
while(i < NO_OF_LOOP)
{
// Awaken or unblocked by thread (i-1)
pthread_mutex_lock(&mutex1);
while (!wakeup[my_id]) {
pthread_cond_wait(&cond[my_id], &mutex1);
}
wakeup[my_id] = 0;
pthread_mutex_unlock(&mutex1);
printf("I am thread - %ld",my_id);
++i;
pthread_mutex_lock(&mutex1);
//tell thread i to wake up
wakeup[(my_id + 1) % NTHREADS] = 1;
pthread_cond_signal(&cond[(my_id + 1) % NTHREADS]);
pthread_mutex_unlock(&mutex1);
}
return NULL;
}
int main(void)
{
pthread_t threadid[NTHREADS];
wakeup[0] = 1; //let thread 0 start.
РЕДАКТИРОВАТЬ. Еще одна ошибка с #define NTHREADS MULTIPLE_THREADS*64
тоже. Выражение (my_id + 1) % NTHREADS
не будет правильно оценено, макрос должен быть
#define NTHREADS (MULTIPLE_THREADS*64)
Поскольку stdout обычно буферизируется по строке, добавьте новую строку в ваш printf, чтобы вы могли сразу увидеть вывод.
printf("I am thread - %ld\n",my_id);
wakeup[0] = 1;
в main () довольно важно.