线程间同步——信号量控制(Semaphore)

上一篇生产者-消费者的例子是基于链表的,其空间可以动态分配,现在基于固定大小的环形
队列重写这个程序,这次不再利用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方式):

以上是 线程间同步——信号量控制(Semaphore) 的全部内容, 来源链接: utcz.com/z/267488.html

回到顶部