信号量是一个计数器,用于多个进程提供对共享数据的访问
为了获取共享数据,进程需要执行下列操作:
- 测试控制该信号的信号量
- 若此信号量为正,则进程可以使用该资源。在这种情况下,进程会将信号量值减1,表示它使用了一个资源单位
- 否则,若此信号量为0,则进程进入休眠状态,直至信号量大于0.进程被唤醒,它返回步骤1.
为了正确的实现信号量,信号量的值的测试以及减1操作应当是原子操作。为此,信号量通常是在内核中进行是实现的。
常用的信号量形式被称为二元信号量,它控制单个资源,其初始值为1.但是,一般而言,信号量的初值可以是任意一个正值,该值表明有多少个共享资源单位可供共享使用。
示例:
用信号量实现生产者消费者模型
#include<iostream>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
using namespace std;
#define NUM 5
int queue[NUM]; //全局数组实现环形队列
sem_t blank_number,product_number; //空格子信号量,产品信号量
void*producer(void *arg)
{
int i=0;
while(1){
sem_wait(&blank_number); //生产者将空格子数--,为0则阻塞等待
queue[i]=rand()%1000 +1; //生产一个商品
cout<<"producer:"<<queue[i]<<endl;
sem_post(&product_number); //将产品数++
i=(i+1) % NUM; //借助下标实现环形
sleep(rand()%3);
}
}
void*consumer(void *arg)
{
int i=0;
while(1){
sem_wait(&product_number); //消费者将产品数--,为0则阻塞等待
cout<<"consumer:"<<queue[i]<<endl;
queue[i] = 0; //消费掉一个产品
sem_post(&blank_number); //将空格子数++
i=(i+1) % NUM; //借助下标实现环形
sleep(rand()%3);
}
}
int main()
{
pthread_t pid,cid;
sem_init(&blank_number, 0, NUM); //初始化空格子信号量为5
sem_init(&product_number, 0, 0); //产品数为0
pthread_create(&pid, NULL, producer, NULL);
pthread_create(&cid, NULL, consumer, NULL);
pthread_join(pid, NULL);
pthread_join(cid, NULL);
sem_destroy(&blank_number);
sem_destroy(&product_number);
return 0;
}