信号量:
功能: 实现线程间的同步与互斥
本质:一个计数器(做资源计数-判断当前是否能对临界资源进行操作)+等待+唤醒 +等待队列
原理:
互斥原理:只具有0或1计数时,就可以实现互斥,初始计数为1,1表示当前只有一个线程能获取资源;
获取资源之后-1,等操作完后+1,当计数为0时,其他线程进行等待(将PCB加入到等待队列)
同步原理:对程序逻辑进行控制(对临界资源合理操作控制);通过计数判断当前是否能够对临界资
源进行访问,不能操作(计数<=0),则等待;
相关接口
定义信号量变量
变量类型: sem_t 头文件: #include <semaphore.h>
初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem: 定义的信号变量
pshared:0表示线程中的信号, 非零表示进程间的信号量
value: 信号量初始值
销毁信号量
int sem_destroy(sem_t* sem);
等待信号量
功能:等待信号量,会将信号量的值减1
int sem_wait(sem_t *sem);
发布信号量
功能:发布信号量,表示资源使用完毕,可以归还资源了。将信号量值加1。
int sem_post(sem_t *sem);
通过信号量实现生产者消费者模型
过程: 生产者线程向仓库(一个环形队列)加入数据, 消费者线程在这个仓库中取出数据
封装模型类
具体代码如下:
#include <iostream>
#include <semaphore.h>
#include <pthread.h>
#include <vector>
#include <stdio.h>
using namespace std;
#define MAX_SOTR 5
class Sem_PC_test{
private:
sem_t _lock; // 用于实现储存仓库的互斥
sem_t _data; // 用于实现消费者线程仓库容量的计数
sem_t _prod; // 用于实现生产者线程仓库容量的计数
vector<int> _stor; // 定义一个仓库
int _wirte; // 写的位置用于实现环形队列
int _read; // 读的位置用于实现环形队列
public:
Sem_PC_test(const int cap = MAX_SOTR)
:_stor(cap)
,_wirte(0)
,_read(0)
{
sem_init(&_lock, 0, 1); // 初始化锁
sem_init(&_data, 0, 0);
sem_init(&_prod, 0, MAX_SOTR);
}
~Sem_PC_test()
{
sem_init(&_lock, 0, 1);
sem_init(&_data, 0, 0);
sem_init(&_prod, 0, MAX_SOTR);
}
bool Push_data(const int& data)
{
sem_wait(&_prod); // 生产者线程获取信号值
sem_wait(&_lock); // 加锁
_stor[_wirte] = data; //写入数据
_wirte = (_wirte+1)% MAX_SOTR; // 实现环形队列
sem_post(&_lock); // 发布信号(开锁)
sem_post(&_data);// 向消费者线程的条件变量发布信号
return true;
}
bool Get_data(int& data)
{
sem_wait(&_data);
sem_wait(&_lock);
data = _stor[_read];
_read = (_read+1)% MAX_SOTR;
sem_post(&_lock);
sem_post(&_prod);
return true;
}
};
void* test_get(void* agr)
{
int a;
while(1)
{
Sem_PC_test* p = (Sem_PC_test*)agr;
p->Get_data(a);
printf("线程%lu,获取到值%d\n", pthread_self(), a);
}
return NULL;
}
void* test_push(void* agr)
{
static int i = 0;
while(1)
{
Sem_PC_test* p = (Sem_PC_test*)agr;
p->Push_data(i);
i++;
}
return NULL;
}
int main()
{
pthread_t tid[4], PC[4];
int i;
Sem_PC_test data;
for(i=0; i<4; i++)
{
pthread_create(&tid[i], NULL ,test_get , (void*)&data);
}
for(i=0; i<4; i++)
{
pthread_create(&PC[i], NULL , test_push, (void*)&data);
}
for(i=0; i<4; i++)
{
pthread_join(tid[i],NULL);
}
for(i=0; i<4; i++)
{
pthread_join(PC[i],NULL);
}
return 0;
}
编译代码: g++ Sem_PC_test.cpp -o Sem_PC_test -lpthread
运行结果如下: