POSIX条件变量

来源:互联网 发布:淘宝不能申请退款 编辑:程序博客网 时间:2024/05/16 05:22
当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。
例如一个线程访问队列时,发现队列为空,它只能等待,只到其它线程将一个节点添加到队列中。这种情况就需要用到条件变量。

条件变量函数
pthread_cond_init
pthread_cond_destroy
pthread_cond_wait
pthread_cond_signal
pthread_cond_broadcast

条件变量使用规范
等待条件代码
pthread_mutex_lock(&mutex);
while (条件为假)
pthread_cond_wait(cond, mutex);
修改条件
pthread_mutex_unlock(&mutex);

给条件发送信号代码
pthread_mutex_lock(&mutex);
设置条件为真
pthread_cond_signal(cond);
pthread_mutex_unlock(&mutex);

pctest.c
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <semaphore.h>


#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>


#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        } while(0)


#define CONSUMERS_COUNT 2
#define PRODUCERS_COUNT 4


pthread_mutex_t g_mutex;
pthread_cond_t g_cond;


pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT];


int nready = 0;


void* consume(void *arg)
{
int num = (int)arg;
while (1)
{
pthread_mutex_lock(&g_mutex);
while (nready == 0)
{
printf("%d begin wait a condtion ...\n", num);
pthread_cond_wait(&g_cond, &g_mutex);
}

printf("%d end wait a condtion ...\n", num);
printf("%d begin consume product ...\n", num);
--nready;
printf("%d end consume product ...\n", num);
pthread_mutex_unlock(&g_mutex);
sleep(1);
}
return NULL;
}


void* produce(void *arg)
{
int num = (int)arg;
while (1)
{
pthread_mutex_lock(&g_mutex);
printf("%d begin produce product ...\n", num);
++nready;
printf("%d end produce product ...\n", num);
pthread_cond_signal(&g_cond);
printf("%d signal ...\n", num);
pthread_mutex_unlock(&g_mutex);
sleep(1);
}
return NULL;
}


int main(void)
{
int i;


pthread_mutex_init(&g_mutex, NULL);
pthread_cond_init(&g_cond, NULL);




for (i=0; i<CONSUMERS_COUNT; i++)
pthread_create(&g_thread[i], NULL, consume, (void*)i);


sleep(1);


for (i=0; i<PRODUCERS_COUNT; i++)
pthread_create(&g_thread[CONSUMERS_COUNT+i], NULL, produce, (void*)i);

for (i=0; i<CONSUMERS_COUNT+PRODUCERS_COUNT; i++)
pthread_join(g_thread[i], NULL);


pthread_mutex_destroy(&g_mutex);
pthread_cond_destroy(&g_cond);


return 0;
}

makefile:
.PHONY:clean all
CC=gcc
CFLAGS=-Wall -g
BIN=pctest
all:$(BIN)
%.o:%.c
$(CC) $(CFLAGS) -c $< -o $@
pctest:pctest.o
$(CC) $(CFLAGS) $^ -o $@ -lpthread
clean:
rm -f *.o $(BIN)


0 0