信号量
头文件 - semaphore.h
信号量类型
sem_t sem;------》本质int
相关函数
初始化信号量
sem_init(sem_t *sem, int pshared, unsigned int value);
参数:
pshared: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, xxxxx);
解锁
sem_post(sem_t *sem);
对sem做了++操作
测试
使用信号量实现生产者,消费者模型
测试源码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
sem_t produce_sem;
sem_t custom_sem;
typedef struct node
{
int data;
struct node* next;
}Node;
Node* head = NULL;
// 操作套路:先对自己的做P操作,减少自己的,然后再对对方的做V操作,增加对方的。
void* producer(void* arg)
{
while(1)
{
sem_wait(&produce_sem); // porduce_sem -- == 0, 阻塞
Node * node = (Node*)malloc(sizeof(Node));
node->data = rand() % 1000;
node->next = head;
head = node;
printf("+++++ 生产者:%lu, %d\n", pthread_self(), node->data);
sem_post(&custom_sem); // custom_sem++
sleep(rand()%5);
}
return NULL;
}
void* customer(void* arg)
{
while(1)
{
sem_wait(&custom_sem);
Node* del = head;
head = head->next;
printf("----- 消费者:%lu, %d\n", pthread_self(), del->data);
free(del);
sem_post(&produce_sem);
sleep(rand()%5);
}
return NULL;
}
int main(int argc, const char* argv[])
{
pthread_t thid[2];
// 初始化信号量
sem_init(&produce_sem, 0, 4); // 初始化生产者线程信号量
sem_init(&custom_sem, 0, 0); // 初始化消费者线程信号量
pthread_create(&thid[0], NULL, producer, NULL);
pthread_create(&thid[1], NULL, customer, NULL);
for(int i=0; i<2; ++i)
{
pthread_join(thid[i], NULL);
}
sem_destroy(&produce_sem);
sem_destroy(&custom_sem);
return 0;
}
测试结果
关键代码分析
对比实际的交通信号灯,在一个十字路口,需要有2组信号量,首先是东西方向绿灯,南北方向红灯,东西方向的车可以通行。需要变灯的时候,需要先将东西方向自己的绿灯变成红灯,也就是set_wait(&self),然后再将南北方向的红灯变成绿灯,也就是set_post(&other)。
对应在代码下就是下面的样子: