linux系统编程:线程同步-信号量(semaphore)

2023-11-02

                             线程同步-信号量(semaphore)

生产者与消费者问题再思考

在实际生活中,只要有商品,消费者就可以消费,这没问题。但生产者的生产并不是无限的,例如,仓库是有限的,原材料是有限的,生产指标受消费指标限制等等。为了进一步,解决好生产者与消费者问题,引入信号量进机制。


信号量

信号量(semaphore)是互斥量的升级版:互斥量的状态为0或1,而信号量可以为n。也就是说,使用互斥量时,最多允许一个线程进入关键区,而信号量允许多个,具体值是信号量当前的内部值。


相关函数

sem_t       //信号量类型
sem_init(sem_t *sem, int pshared, unsigned int value);
sem_wait(sem_t *sem)
sem_trywait
sem_timedwait
sem_post(sem_t *sem)
sem_destroy
重要的是理解:sem_wait和sem_post两个函数。

sem_wait(sem);当sem为零时,线程阻塞;否则,sem减一,线程不阻塞。

sem_post(sem);sem加一。

此外,使用sem_init方法,对信号量类型初始化,第二个参数,默认是0,标明用于线程之间。第三个参数指定了初始值。


单生产者与单消费者

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM 5
sem_t blank_num, product_num;
int i, j, k;
int goods[NUM];
void *producer(void *argv)
{
	while (1)
	{
		sem_wait(&blank_num);
		goods[i] = rand() % 100 + 1;
		printf("produce %d\n", goods[i]);
		sem_post(&product_num);
		i = (i + 1) % NUM;
		sleep(rand() % 2);
	}
}
void *comsumer(void *argv)
{
	while (1)
	{
		sem_wait(&product_num);
		printf("comsume %d\n", goods[j]);
		goods[j] = 0;
		sem_post(&blank_num);
		j = (j + 1) % NUM;
		sleep(rand() % 2);
	}
}
int main(void)
{
	i = j = k = 0;
	//初始化信号量
	sem_init(&blank_num, 0, NUM);
	sem_init(&product_num, 0, 0);
	pthread_t pro, com;
	pthread_create(&com, NULL, producer, NULL);
	pthread_create(&pro, NULL, comsumer, NULL);
	pthread_join(com, NULL);
	pthread_join(pro, NULL);
	sem_destroy(&blank_num);
	sem_destroy(&product_num);
	return 0;
}


多生产者与多消费者

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM 5
pthread_mutex_t m1, m2;
sem_t blank_num, product_num;
int goods[NUM];
int i, j, k;
void *producer(void *argv)
{
	while (1)
	{
		sem_wait(&blank_num);
		pthread_mutex_lock(&m1);
		goods[i] = rand() % 100 + 1;
		printf("produce %d\n", goods[i]);
		i = (i + 1) % NUM;
		pthread_mutex_unlock(&m1);
		sem_post(&product_num);
		sleep(rand() % 2);
	}
}
void *comsumer(void *argv)
{
	while (1)
	{
		sem_wait(&product_num);
		pthread_mutex_lock(&m2);
		printf("comsume %d\n", goods[j]);
		goods[j] = 0;   //置零
		j = (j + 1) % NUM;
		pthread_mutex_unlock(&m2);
		sem_post(&blank_num);
		sleep(rand() % 2);
	}
}
int main(void)
{
	i = j = k = 0;
	//初始化信号量及互斥量
	sem_init(&blank_num, 0, NUM);
	sem_init(&product_num, 0, 0);
	pthread_mutex_init(&m1, NULL);
	pthread_mutex_init(&m2, NULL);
	pthread_t pro[2], com[3];
	for (k = 0; k < 3; k++)
		pthread_create(&com[k], NULL, producer, NULL);
	for (k = 0; k < 2; k++)
		pthread_create(&pro[k], NULL, comsumer, NULL);
	for (k = 0; k < 3; k++)
		pthread_join(com[k], NULL);
	for (k = 0; k < 2; k++)
		pthread_join(pro[k], NULL);
	pthread_mutex_destroy(&m1);
	pthread_mutex_destroy(&m2);
	sem_destroy(&blank_num);
	sem_destroy(&product_num);
	return 0;
}


     

CCPP Blog 目录


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux系统编程:线程同步-信号量(semaphore) 的相关文章

  • 主线程退出后,子线程会不会退出

    额 好吧 这是个标题党 其实所有的线程都是平级的 根本不存在主线程和子线程 下文所述为了方便 将在main函数中的线程看做主线程 其它线程看成子线程 特此说明 先考虑以下代码 include
  • 如何在 Delphi 中实现线程安全列表包装器?

    我有一个列表包装器 它维护两个 Tstringlists 和一个 TClassList 我需要它是线程安全的 这样 不允许并发写入 应进入某种等待状态 不允许边写边读 反之亦然 应该进入某种等待状态 并发读取are allowed 关于我如
  • 为什么我的dispatch_once会陷入僵局?

    为什么我会陷入僵局 void foo static dispatch once t onceToken dispatch once onceToken self foo whatever 我预计foo第一次调用时执行两次 现有的答案都不是很
  • 在 C# 中使用信号量

    嗨 我正在尝试使用Semaphore在我的应用程序中 我已经这样声明了 class MyThread public Thread Thrd static Semaphore sem new Semaphore 2 2 public MyTh
  • C 信号量:sem_wait 抛出莫名其妙的错误

    我正在研究一个必须使用信号量来解决的问题 我有一个包含两个信号量的数组 gsem 并给定某些条件调用sem wait gsem me 它应该等待直到该特定进程被唤醒 但是 由于某种原因它给了我错误Bad file descriptor 我抬
  • 在C++中使用线程交替打印奇数和偶数

    使用线程打印奇偶数我遇到了这个问题并想讨论 C 中的解决方案 我能想到使用2个二进制信号量奇数和偶数信号量 偶数信号量初始化为 1 奇数信号量初始化为 0 T1 thread function funOdd wait even print
  • 浴室同步和线程队列

    对于家庭作业 我们被要求解决浴室同步问题 我一直在努力思考如何开始 当一个人进入洗手间 personEnterRestrrom 函数 时我想要做什么 如果他们是女性并且没有男性在他们进入的洗手间里 如果不是 他们会进入等待女性的队列 我想为
  • 寻找监视器与信号量的良好类比/示例

    监视器应该解决并发环境中的信号量问题 我正在寻找使用监视器与信号量的良好类比 请使用信息进行类比 4 个任务 任务S 任务 任务 任务S 1 个变量 varX 每个任务都想根据某个事件来操作varX 假设一群病人想要去看医生 信号量的实现是
  • 如何在 Web Api 操作中锁定长异步调用?

    我有这样的场景 我有一个 WebApi 和一个端点 触发时会执行大量工作 大约 2 5 分钟 这是一个具有副作用的 POST 端点 我想限制执行 以便如果向此端点发送 2 个请求 不应该发生 但安全总比遗憾更好 其中一个请求将必须等待以避免
  • ReleaseSemaphore 不释放信号量

    简而言之 main 的 WaitForSingleObject 在下面的程序中挂起 我正在尝试编写一段代码来调度线程并等待它们完成后再恢复 我没有每次都创建线程 成本高昂 而是让它们休眠 主线程创建 X 个处于 CREATE SUSPEND
  • 使用 Java 在线程之间传输数据

    我正在编写一个模仿电影院的多线程应用程序 每个参与的人都是自己的线程 并发必须完全由信号量来完成 我遇到的唯一问题是如何基本上链接线程以便它们可以通信 例如通过管道 例如 Customer 1 是一个线程 它获取一个信号量 让它走到票房 现
  • RedHat Enterprise Linux 5.3 及以上版本不正确支持 sem_timedwait?

    我们在使用 pthreadsem timedwait 的 RedHat Enterprise Linux 系统上看到了奇怪的行为 仅 5 3 及以上版本才会出现此情况 当我们使用 sem init 在后台线程上创建信号量时 不会返回错误 当
  • 信号量和同步

    我不太明白 javadocs 中信号量描述中的以下内容 注意 没有同步锁 当 acquire 被调用时持有 会阻止一个项目被 回到了水池 信号量 封装同步 需要限制对池的访问 与任何同步分开 需要保持一致性 泳池本身 有人可以帮助我理解这一
  • 计数信号量和二进制信号量之间的区别

    计数和二进制信号量有什么区别 我在某处看到的是 两者都可以控制 N 个请求资源的进程 两者都拥有自由邦 二进制信号量和计数信号量可以保护的资源数量是否有限制 两者都只允许一个进程一次使用一种资源 还有其他区别吗 上述属性是否正确 实际上 这
  • PHP 无需等待 sem_acquire?

    不是特定的代码问题 而是一般的代码问题 我试图在工作项目中使用信号量来限制可以同时访问某些进程的用户数量 据我了解如下 iKey ftock sSomeFileLocation sOneCharacterString Generate th
  • 信号量 P 和 V 操作是原子操作吗?

    可以在信号量上执行的 P 和 V 操作是否保证原子操作 信号量可以防止两个进程进入 P 吗 假设我们有一个二进制信号量 s 其值为 1 并且两个进程同时尝试在 s 上执行 P 这些操作中只有一个能够在 s 上的下一个 V 操作之前完成 尝试
  • python 中的公平信号量

    python 中是否有可能有一个公平的信号量 它可以保证阻塞线程按照它们调用的顺序解除阻塞acquire 您可能必须用其他活动部件来构建一个 例如 创建一个Queue Queue 每个听众都会发布一个全新的Event 然后它会等待 当需要唤
  • 用餐哲学家挨饿的可能性

    我需要检查解决哲学家就餐问题的算法是否保证满足以下所有条件 不存在僵局的可能性 没有挨饿的可能 我正在使用信号 http en wikipedia org wiki Semaphore 28programming 29放在筷子上即可解决问题
  • .NET 紧凑框架中的信号量

    不幸的是 使用 NET Compact Framework 时 System Threading 中没有信号量 我不确定为什么会这样 有人有想法吗 经过谷歌搜索后 我发现很多人给出了他们自己的实现 但他们中没有一个真正工作得很好 或者根本没
  • 如何让 UI 线程等待信号量,同时处理其他调度程序请求? (就像 MessageBox.Show 本身所做的那样)

    通常 当 UI 线程调用类似的东西时MessageBox Show 当前代码执行不会继续 直到用户单击 确定 但程序将继续运行在 UI 线程上分派的其他代码 In 这个问题 https stackoverflow com questions

随机推荐

  • antd中Form.Item无法获取到对应的表单值解决

    antd中Form Item无法获取到对应的表单值解决 前言 问题代码示例 解决 前言 本文章讲的解决方案只是其中一种 无法获得对应表单的原因有很多 只能在今后的道路上慢慢采坑然后避免 问题代码示例 import React Compone
  • Retrofit中的注解原理项目实战

    今天我们来聊聊这个最近很火的网络请求库retrofit 在此基础上会延伸出一些列的知识点 现在关于retrofit的文章很多 我之所以写这篇文章的原因在于 8月份负责假设新客户端底层的过程中首次尝试使用该库 并取得非常不错的效果 不到20天
  • 计算机视觉最新技术:YOLOv8等前沿算法推荐!

    计算机视觉最新技术 YOLOv8等前沿算法推荐 计算机视觉是人工智能领域中的一个重要方向 它涉及到图像 视频等多媒体形式的信息处理 而随着人工智能技术的不断发展 计算机视觉领域也不断涌现出新的算法和模型 其中 YOLOv8等一系列算法被认为
  • 初识springcloud(微服务)

    1 微服务的定义 microservice 1 多个微服务开发的依然是一个完整的应用 2 微服务都会独立运行在一个独立的进程里面 3 微服务之间通常会采用轻量级的通信机制来进行通信 比如http https socket netty dub
  • python 视频流分析,通过ffmpeg管道将视频输出流到Python脚本中进行分析。如何导入python?...

    我正在与其他库一起编写一个脚本 它需要RGB24格式的帧或图像 为了提高兼容性 我决定允许外部管道将帧流式传输到这个程序中 每次在代码中使用更改设备或源代码可能会变得乏味 使用解析器简单地指定源代码会导致语法错误 示例 ffmpeg f d
  • python如何更新包

    python如何更新包 更多python视频教程请到菜鸟教程https www piaodoo com Python安装新包 pip是很好用的安装工具 pip list 可以查询所有已安装的包和版本 怎么知道本地安装包的版本是否有可以更新的
  • Python模拟智能开关设备MQTT接入阿里云物联网平台 - PyCharm paho.mqtt

    概要 Python 使用 paho mqtt 库 利用阿里云物联网平台的设备证书 productKey deviceName deviceSecret 自动合成 userName passWord 以MQTT通信协议接入阿里云物联网平台 并
  • IPFS搭建私有网络

    87条消息 IPFS 节点搭建 躺在家里不干活的博客 CSDN博客 ipfs节点搭建 一 安装go ipfs 1 下载 下载地址https gitee com wang ya nan go ipfs releases wget https
  • Hadoop Spark 常见问题【一】

    Spark 1 RDD 数据集拆分 数据存储在内存或者磁盘 多分区 失效自动重构 转换操作构造 2 RDD俩种依赖 窄依赖 父RDD中的分区最多只能被一个子RDD的一个分区使用 和宽依赖 子RDD依赖于所有父RDD 3 spark 角色 1
  • APS高级计划排程系统和生产排产系统

    一 什么是APS系统 高级计划与排程APS Advanced Planning and Scheduling 是指在考虑生产资源约束的前提下 通过优化方法 为生产加工任务精确安排生产资源和计划生产时间 使生产及时完成 并使资源充分利用 AP
  • 【WebRTC 02】从摄像头获取视频以及切换分辨率和视频源

    上一节中我们已经搭建出了用于操作的环境 这一节我们要实现的一个小目标 就是将电脑摄像头拍到的内容实时显示到网页上 同时我们一起学习下原理 并做一些小拓展 文章目录 操作环境 实现效果 几个概念 HTML5中的Audio和Video API
  • C++项目练手:矩阵类的功能实现

    C 项目练手 矩阵类的功能实现 C 课程设计 矩阵类的相关功能实现 矩阵简述 实数矩阵是由一个按照长方阵列排列的实数集合 除数据外 两个实数矩阵可以进行加法和乘法运算 一个矩阵也可以和一个实数相乘 得到一个新的矩阵 请基于抽象出的矩阵的属性
  • JavaScript进阶之高阶函数(Higher-order function)

    你还在以为 map reduce filter 是高阶函数吗 高阶函数听上去很让人不明觉厉 但其实也并没有什么特别厉害的地方 只是网上的定义一直让我们有点模糊而已 接下来我们来详细讲讲 首先是定义 查自百度百科 定义 在数学和计算机科学中
  • 二进制安装docker

    二进制安装docker文档 建模部署 docker安装 下载docker 因rpm包安装依赖较多 选择二进制安装 下载地址如下 https download docker com linux static stable x86 64 创建d
  • 区域生长

    转自 https blog csdn net qq 37764129 article details 81227091 注 本程序只能做图像分割 结果图是转自原作者的 暂时没实现该功能 1 理论基础 区域生长算法的基本思想是将有相似性质的像
  • 称重问题递归解法

    用天平称重时 我们希望用尽可能少的砝码组合称出尽可能多的重量 如果只有5个砝码 重量分别是1 3 9 27 81 则它们可以组合称出1到121之间任意整数重量 砝码允许放在左右两个盘中 本题目要求编程实现 对用户给定的重量 给出砝码组合方案
  • 【小沐学NLP】Python实现中文、英文分词

    NLP开发系列相关文章编写如下 1 小沐学NLP Python实现词云图 2 小沐学NLP Python实现图片文字识别 3 小沐学NLP Python实现中文 英文分词 4 小沐学NLP Python实现聊天机器人 ELIZA 5 小沐学
  • win10 提供管理员权限才能删除文件夹

    计算机管理员帐户 也就是我们熟知的 Administrator 拥有可执行影响其他用户操作的权限 由于win10专业版刚发布 很多用户不知道怎么取得管理员权限 接下来小编就跟大家分享启用管理员权限的方法 1 打开win10专业版的开始菜单中
  • 手把手教你--JAVA微信支付(H5支付)

    概述 之前说过 有时间把微信支付的H5支付讲解下 一直拖了半年时间 最近的项目正好又温习了支付功能 趁着热乎 抓紧起来 微信的H5支付 相对公众号支付 容易了跟多 很多相似的东西 也有不同之处 这里只介绍H5支付的关键点 其他内容请先去看我
  • linux系统编程:线程同步-信号量(semaphore)

    线程同步 信号量 semaphore 生产者与消费者问题再思考 在实际生活中 只要有商品 消费者就可以消费 这没问题 但生产者的生产并不是无限的 例如 仓库是有限的 原材料是有限的 生产指标受消费指标限制等等 为了进一步 解决好生产者与消费