LINUX.ORG.RU

pthread_cond_wait помогите разобраться


0

0

Решил организовать очереди с потоками - выяснилось, что что-то не так. Поэтому упростил задачу, чтобы найти причину непонятки.

Есть счетчик counter, защищенный мьютексом counter_mutex. 
Есть два потока, incrementor и decrementor. Первый увеличивает счетчик, второй - уменьшает, причем только до нуля, после чего ожидает сигнала от первого потока. Есть условная переменная cond, защищенная мьютексом cond_mutex. Поток incrementor после увеличения счетчика вызывает pthread_cond_signal(&cond). Я ожидал, что как только incrementor сигналит, decrementor просыпается, однако...
Вопрос: почему incrementor успевает увеличить счетчик очень много раз,
при этом столько же раз просигналив, а потом только decrementor просыпается, уменьшает счетчик до нуля и уже после этого откликается после каждого сигнала. Код прилагается.

#include <pthread.h>

pthread_mutex_t counter_mutex;
pthread_mutex_t cond_mutex;
pthread_cond_t cond;

pthread_t incrementor_thread;
pthread_t decrementor_thread;

int counter;

void* decrementor(void)
{
    printf("decrementor(): called\n");
    while(1)
    {
	while(1)
	{
	    pthread_mutex_lock(&counter_mutex);
	    if(0 == counter)
	    {
		/* nothing to decrement: suspend */
		pthread_mutex_unlock(&counter_mutex);
		break;
	    }

    	    counter--;
	    pthread_mutex_unlock(&counter_mutex);
	    
	} /* inner loop */
	
	pthread_mutex_lock(&cond_mutex);
	printf("decrementor(): suspended\n");
      pthread_cond_wait(&cond, &cond_mutex);
	printf("decrementor(): wake up\n");
      pthread_mutex_unlock(&cond_mutex);

    } /* outer loop */
}

void* incrementor(void *p)
{
    while(1)
    {
	printf("incrementor(): generating packet\n");

	pthread_mutex_lock(&counter_mutex);
	counter++;
	printf("increment_counter(): counter=%d\n", counter);
	pthread_mutex_unlock(&counter_mutex);

	pthread_mutex_lock(&cond_mutex);
	printf("register_packet(): signalling\n");
	pthread_cond_signal(&cond);
	pthread_mutex_unlock(&cond_mutex);
    }
}

int main()
{
      counter = 0;
	
	pthread_mutex_init(&counter_mutex, NULL);
	pthread_mutex_init(&cond_mutex, NULL);
	pthread_cond_init(&cond, NULL);
 
      pthread_create(&decrementor_thread, NULL, decrementor, NULL);
      pthread_create(&incrementor_thread, NULL, incrementor, NULL);
 
	/* loop forever */
	while(1) {
		sleep(10);
	}
	
	return 0;
}

Ответ на: комментарий от fghj

Я еще не знаю, что такое семафоры. Так вы можете ответить на вопрос?

instead
() автор топика

> почему incrementor успевает увеличить счетчик очень много раз,
> при этом столько же раз просигналив, а потом только decrementor просыпается

Потому что никто не гарантирует, что какой-то "поток" будет работать столько-то,
а потом отдаст время на столько-то, они могут работать по какому угодно расписанию, например на моей машине работает сначала decrementor, а потом только incrementor.

fghj ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.