上一篇生产者-消费者的例子是基于链表的,其空间能够动态分配,当初基于固定大小的环形
队列重写这个程序,这次不再利用mutex而是semaphore来实现线程间同步!
上一篇文章链接:https://segmentfault.com/a/11...
仍旧是生产者生产一个构造体串在链表的表头上,消费者从表头取走构造体,生产者未生产或生产的曾经被拿完,则消费者须要挂起期待.
1 #include <stdlib.h> 2 #include <pthread.h> 3 #include <stdio.h> 4 #include <semaphore.h> 5 6 #define NUM 5 7 int queue[NUM]; 8 sem_t blank_number, product_number; 9 10 void *producer(void *arg) 11 { 12 int p = 0; 13 while (1) { 14 sem_wait(&blank_number);//wait能够取得信号,使init初始化中semaphore值-1,如果减到0则挂起期待,胜利取 用后持续进行后续操作 15 queue[p] = rand() % 1000 + 1; 16 printf("Produce %d\n", queue[p]); 17 sem_post(&product_number);//能够开释上述操作所占用的资源并唤醒期待执行的下个线程,并且使semaphore的> 值+1 18 p = (p+1)%NUM;//循环队列+1 19 sleep(rand()%5); 20 } 21 } 22 23 void *consumer(void *arg) 24 { 25 int c = 0; 26 while (1) { 27 sem_wait(&product_number);//此时product线程的semophore值曾经从init中的0变1,故此处有1个资源可供wait应用,不会阻塞!取用后在此变回0,但能够执行 后续操作了。 28 //此处因为还有一个信号可供wait取用,胜利取用而后持续后续操作 29 printf("Consume %d\n", queue[c]); 30 queue[c] = 0;//取用过的队列值设为0,便于察看过程间是否同步(即是否consumer取了曾经取过的队列值:) 31 sem_post(&blank_number);//开释一个信号(此处开释的是wait后续操作所占用的线程信号)给blank_number并唤醒下一个阻塞或期待中的过程,semaphore+1 32 c = (c+1)%NUM; 33 sleep(rand()%5); 34 } 35 } 36 37 int main(int argc, char *argv[]) 38 { 39 pthread_t pid, cid; 40 41 sem_init(&blank_number, 0, NUM); 42 sem_init(&product_number, 0, 0); 43 pthread_create(&pid, NULL, producer, NULL); 44 pthread_create(&cid, NULL, consumer, NULL); 45 pthread_join(pid, NULL); 46 pthread_join(cid, NULL); 47 sem_destroy(&blank_number); 48 sem_destroy(&product_number); 49 return 0; 50 }
linux环境下执行:
gcc semaphore.c -o semaphore -lpthread
./semaphore
执行后果如下(FIFO形式):