当前位置:网站首页>线程同步之信号量
线程同步之信号量
2022-06-27 13:29:00 【StudyWinter】
1 基本概念
- 简单的说就是进化版的互斥锁(1~N)计数器
- 记录当前可利用的资源数,当资源数量<=0时会阻塞,当资源数量>时才开始进行操作,另外信号量的操作均为原子操作。
由于互斥锁的粒度比较大,如果我们希望在多个线程间对某一对象的部分数据进行共享,使用互斥锁是没有办法实现的,只能将整个数据对象锁住。这样虽然达到了多线程操作共享数据时保证数据正确性的目的,却无形中导致线程的并发性下降。线程从并行执行,变成了串行执行。与直接使用单进程无异。信号量,是相对折中的一种处理方式,既能保证同步,数据不混乱,又能提高线程并发。
2 函数使用
2.1 sem_init函数
作用:初始化一个信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
// 参 1:sem 信号量
// 参 2:pshared 取 0 用于线程间;取非 0(一般为 1)用于进程间
// 参 3:value 指定信号量初值信号量的初值,决定了占用信号量的线程(进程)的个数。
2.2 sem_destroy函数
作用:销毁一个信号量
int sem_destroy (sem_t *sem);2.3 sem_wait函数
作用:给信号量加锁--
int sem_wait(sem_t *sem);2.4 sem_post 函数
作用:给信号量解锁 ++
int sem_post(sem_t *sem);2.5 sem_trywait 函数
作用:尝试对信号量加锁 – (与 sem_wait 的区别类比 lock 和 trylock)
int sem_trywait(sem_t *sem);2.6 sem_timedwait 函数
作用:限时尝试对信号量加锁 --
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
// 参 2:abs_timeout 采用的是绝对时间。3 信号量实现的生产者和消费者

根据注释,代码还是比较好理解的。两个信号量来控制,一个初始为0,表示一开始生产的数量为0.另外一个初始的数量是可以存放商品的空格数,初始化就是格子数N。
互斥和条件变量的方式是我消费 你不能生产。 而两个信号量是你生产 我可以消费。毕竟环形的不影响,最多你生产了,我不知道。就怕多个生产者 ,你格子放入了还没移到下一个格子我又重复放入了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM 5
int queue[NUM]; // 全局数组模拟实现环形队列
sem_t black_number, product_number; // 空格子信号量。产品信号量
// 生产者回调函数
void* producer(void* arg) {
int i = 0;
int res = 0;
while (1) {
// 空格子信号量加锁,将空格数减一,为0则阻塞等待
res = sem_wait(&black_number);
if (res != 0) {
fprintf(stderr, "sem_wait black_number error:%s\n", strerror(res));
exit(1);
}
// 模拟生产一个产品
queue[i] = rand() % 1000 + 1;
printf("------Produce---%d\n", queue[i]);
// 产品信号量解锁,将产品++
res = sem_post(&product_number);
if (res != 0) {
fprintf(stderr, "sem_post product_number error:%s\n", strerror(res));
exit(1);
}
i = (i + 1) % NUM;
sleep(rand() % 2);
}
}
// 消费者回调函数
void* consumer(void* arg) {
int i = 0;
int res = 0;
while (1) {
// 消费者将产品数量--,为0则阻塞等待
res = sem_wait(&product_number);
if (res != 0) {
fprintf(stderr, "sem_wait product_number error:%s\n", strerror(res));
exit(1);
}
printf("==============================Consumer=========%d\n", queue[i]);
// 消费一个产品
queue[i] = 0;
// 消费后将空格数++
res = sem_post(&black_number);
if (res != 0) {
fprintf(stderr, "sem_post black_number error:%s\n", strerror(res));
exit(1);
}
// 模拟环形队列
i = (i + 1) % NUM;
sleep(rand() % 5);
}
}
int main(int argc, char** argv) {
// 生产者线程和消费者线程
pthread_t pid, cid;
// 初始化空格子信号量,信号量为5,线程间共享----0
int res = sem_init(&black_number, 0, NUM);
if (res != 0) {
fprintf(stderr, "sem_init black_number error:%s\n", strerror(res));
exit(1);
}
// 初始化产品信号量,产品数量是0
res = sem_init(&product_number, 0, 0);
if (res != 0) {
fprintf(stderr, "sem_init product_number error:%s\n", strerror(res));
exit(1);
}
// 创建生产者线程
res = pthread_create(&pid, NULL, producer, NULL);
if (res != 0) {
fprintf(stderr, "pthread_create producer error:%s\n", strerror(res));
exit(1);
}
// 创建消费者线程
res = pthread_create(&cid, NULL, consumer, NULL);
if (res != 0) {
fprintf(stderr, "pthread_create consumer error:%s\n", strerror(res));
exit(1);
}
// 回收线程
res = pthread_join(pid, NULL);
if (res != 0) {
fprintf(stderr, "pthread_join producer error:%s\n", strerror(res));
exit(1);
}
res = pthread_join(cid, NULL);
if (res != 0) {
fprintf(stderr, "pthread_join consumer error:%s\n", strerror(res));
exit(1);
}
// 销毁信号量
res = sem_destroy(&black_number);
if (res != 0) {
fprintf(stderr, "sem_destroy black_number error:%s\n", strerror(res));
exit(1);
}
res = sem_destroy(&product_number);
if (res != 0) {
fprintf(stderr, "sem_destroy product_number error:%s\n", strerror(res));
exit(1);
}
return 0;
}执行

边栏推荐
- IJCAI 2022 | greatly improve the effect of zero sample learning method with one line of code. Nanjing Institute of Technology & Oxford proposed the plug and play classifier module
- 万物互联时代到来,锐捷发布场景化无线零漫游方案
- Postman如何设置成中文?(汉化)
- L June training (day 27) - figure
- 内网学习笔记(8)
- Using FRP tool to realize intranet penetration
- Good luck today
- 每日刷题记录 (六)
- Quickly set up a website to visit foreign countries, set up SS and start BBR to quickly surf the Internet
- Firewall foundation Huawei H3C firewall web page login
猜你喜欢
随机推荐
Can flush open an account for stock trading? Is it safe?
Details of istio micro service governance grid traffic management core resource controller
Firewall foundation Huawei H3C firewall web page login
Crane: a new way of dealing with dictionary items and associated data
scrapy
awk 简明教程
美国芯片再遭重击,继Intel后又一家芯片企业将被中国芯片超越
Does Xinhua San still have to rely on ICT to realize its 100 billion enterprise dream?
POSIX AIO -- glibc 版本异步 IO 简介
昨天访问量破记录
Read a poem
【周赛复盘】LeetCode第81场双周赛
快速搭建一个自己的访问国外网站,搭建ss并开启bbr快速上网
手把手教你搭一个永久运行的个人服务器!
重读经典:《The Craft of Research(1)》
scrapy
Daily question brushing record (6)
After 2 years of outsourcing, I finally landed! Record my ByteDance 3 rounds of interviews, hope to help you!
爱可可AI前沿推介(6.27)
PCL库——报错解决:安装时遇到的cmake与anaconda的冲突问题






![[weekly replay] the 81st biweekly match of leetcode](/img/66/03ee4dbb88b0be7486b71cd4059f44.png)

