信号量的头文件 #include<semaphore.h>
信号量不像条件变量那样不是锁,信号量是锁,是互斥锁的加强版。
pthread_mutex_t mutex;这个互斥锁lock(),mutex == 0,unlock(),mutex==1;线程间访问共享资源是串行的。
信号量 sem_t sem; 信号量设置的初始值可以不为1,假设一开始设置信号零的初始值为3;
当第一个线程访问共享资源,那sem的值减一等于2,第二个线程访问共享资源的话在减一等于1,第三个线程访问共享资源在减一等于0,那此时,如果这三个线程都还没有解锁,那么就会阻塞,直到有一个线程解锁信号量加一,下一个线程才可以访问共享资源,这三个访问共享资源的线程是并行访问的,相比于互斥锁而言,提高了效率。
1.信号量类型
sem_t sem;
加强版的互斥锁
2.主要函数
初始化信号量
sem_init(sem_t *sem,int pshared,unsigned int value);
0 线程同步
1 进程同步
value 最多有几个线程操作共享数据
销毁信号量
sem_destroy(sem_t* sem);
加锁--
sem_wait(sem_t *sem);
调用一次相当于sem做了一次--操作
如果sem值为0,线程会阻塞
尝试加锁
sem_trywait(sem_t * sem);
sem == 0,加锁失败,不会阻塞,直接返回
限时尝试加锁
sem_timedwait(sem_t *sem,xxxx);
解锁++
sem_post(sem_t* sem);
释放资源,对sem++
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<pthread.h>
4 #include<string.h>
5 #include<semaphore.h>
6
7 //定义两个信号量
8 sem_t producer_sem;
9 sem_t customer_sem;
10
11 //定义节点
12 typedef struct Node
13 {
14 int data;
15 struct Node *next;
16 }Node;
17
18 Node *head = NULL;
19 void* producer()
20 {
21 while(1)
22 {
23 //一开始,生产者要生产,所以信号量减一
23 //一开始,生产者要生产,所以信号量减一
24 sem_wait(&producer_sem); //--
25 Node *p = (Node *)malloc(sizeof(Node));
26 p->data = rand()%1000;
27 p->next = head;
28 head = p;
29 printf("producer = %d\n",head->data);
30 //当生产完成之后,需要提醒消费者可以消费了,也释放自己占用的信号量
31 sem_post(&customer_sem); //++
32 sleep(rand()%3);
33 }
34
35 return NULL;
36 }
37
38 void *customer()
39 {
40 while(1)
41 {
42 //当信号量不是0的时候,消费者就可以访问共享资源,占用一个信号量,信> 号量减一
43 sem_wait(&customer_sem); //--
44
45 Node *p = head->next;
46 printf("customer = %d\n",head->data);
47 free(head);
48 head = p;
49 //用完之后释放解锁,提醒生产者有多余的信号量,
50 sem_post(&producer_sem); //++
51 sleep(rand()%3);
52 }
53 }
54
55
56 int main()
57 {
58 pthread_t p1,p2;
59 //创建两个线程
60 pthread_create(&p1,NULL,producer,NULL);
61 pthread_create(&p2,NULL,customer,NULL);
62
63 //初始化生产者信号量,有四个线程操作共享资源
64 sem_init(&producer_sem,0,4);
65 //初始化消费者信号量,一开始没有资源,所以消费者一开始阻塞
66 sem_init(&customer_sem,0,0);
67
68
69 //释放信号狼
70 sem_destroy(&producer_sem);
71 sem_destroy(&customer_sem);
72
73
74
75 //等待回收线程
76 pthread_join(p1,NULL);
77 pthread_join(p2,NULL);
78
79 return 0;
80 }