线程的同步

文章目录

  • 线程的同步
    • 同步:
    • 条件变量:
      • `pthread_cond_init()`:
      • `pthread_cond_wait()`
      • `pthread_cond_signal`
      • pthread_cond_broadcast
    • cp问题
        • 伪唤醒
    • 信号量
      • **多线程的互斥用信号量**:
      • **单线程的互斥用锁**:

线程的同步

同步:

让所有的线程获取锁,按照一定的顺序。按照一定的顺序获取资源就是同步。 (顺序性)

条件变量:

条件变量必须依赖于锁的使用

pthread_cond_init():

是用于初始化条件变量的函数,条件变量是多线程编程中的一种同步机制,允许线程在等待某个条件满足时进入休眠状态,并在条件满足时被唤醒。条件变量通常与互斥锁一起使用,以防止竞争条件。

函数原型:

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);

参数

  • cond: 指向要初始化的条件变量的指针。
  • attr: 指向条件变量属性对象的指针。如果传递 NULL,则使用默认属性。

返回值

  • 成功时返回 0
  • 失败时返回一个错误码。

pthread_cond_wait()

是 POSIX 线程库中用于条件变量等待的函数。它使线程进入等待状态,直到某个条件满足。在此过程中,pthread_cond_wait() 会自动释放与条件变量关联的互斥锁,并在条件变量被唤醒时重新获取该互斥锁。这种行为可以防止等待条件的线程占用互斥锁,使得其他线程可以修改条件并唤醒等待线程。

函数原型

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
  • cond: 指向条件变量的指针。
  • mutex: 指向与条件变量关联的互斥锁的指针。

返回值

  • 返回 0 表示成功。
  • 返回错误码表示失败(例如:EINVAL 表示无效的条件变量或互斥锁,EPERM 表示互斥锁未被调用线程持有)。

pthread_cond_signal

是 POSIX 线程库中用于条件变量的一个函数。它的作用是唤醒至少一个等待在指定条件变量上的线程。条件变量通常和互斥锁一起使用,以实现线程间的同步。

int pthread_cond_signal(pthread_cond_t *cond);
  • cond:指向条件变量的指针(pthread_cond_t 类型)。
  • 返回值:如果成功返回 0,如果失败返回错误代码。

pthread_cond_signal 唤醒一个(至少一个)等待在 cond 条件变量上的线程。如果有多个线程在这个条件变量上等待,则唤醒其中的一个线程。该函数不会确保唤醒哪个具体线程,这是由操作系统调度器决定的。

使用场景

条件变量通常用于线程之间的等待和通知机制。例如,生产者-消费者问题中,消费者可能在条件变量上等待,直到生产者生成了新数据并发出信号。

条件变量的典型使用流程

  1. 等待线程:通常使用 pthread_cond_waitpthread_cond_timedwait 函数等待某个条件。

    • 在调用 pthread_cond_wait 之前,必须持有与该条件变量关联的互斥锁(pthread_mutex_t)。
    • 当条件满足并从等待中返回时,线程会自动重新持有该互斥锁。
  2. 通知线程:当条件满足时,调用 pthread_cond_signal(唤醒一个线程)或者 pthread_cond_broadcast(唤醒所有等待的线程)来通知等待的线程。

例子

以下是一个简单的生产者-消费者模型的例子,展示了如何使用 pthread_cond_signal

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int ready = 0; // 共享资源:表示是否有可供消费的数据void* consumer(void* arg) {pthread_mutex_lock(&mutex);// 等待数据准备好while (!ready) {printf("Consumer waiting for data...\n");pthread_cond_wait(&cond, &mutex); // 等待条件变量信号}printf("Consumer received signal and consumed data!\n");// 释放互斥锁pthread_mutex_unlock(&mutex);return NULL;
}void* producer(void* arg) {sleep(1); // 模拟生产者生成数据的过程pthread_mutex_lock(&mutex);ready = 1; // 生产者准备好数据printf("Producer produced data and sending signal...\n");pthread_cond_signal(&cond); // 发出条件信号,唤醒一个等待线程pthread_mutex_unlock(&mutex);return NULL;
}int main() {pthread_t producer_thread, consumer_thread;// 创建消费者和生产者线程pthread_create(&consumer_thread, NULL, consumer, NULL);pthread_create(&producer_thread, NULL, producer, NULL);// 等待线程完成pthread_join(consumer_thread, NULL);pthread_join(producer_thread, NULL);return 0;
}

消费者线程:进入 pthread_cond_wait 状态,等待条件变量上的信号。pthread_cond_wait 会自动释放 mutex,使其他线程可以访问共享资源。

生产者线程:生成数据后,发出 pthread_cond_signal 信号,通知等待的消费者。

当消费者被唤醒后,它重新获取互斥锁并处理共享资源。

pthread_cond_broadcast

是 POSIX 线程库中的一个函数,用于唤醒等待在指定条件变量上的所有线程。与 pthread_cond_signal 不同,pthread_cond_signal 只唤醒一个等待的线程,而 pthread_cond_broadcast 会唤醒所有等待线程。

int pthread_cond_broadcast(pthread_cond_t *cond);

cond:指向条件变量的指针(类型为 pthread_cond_t)。
返回值:如果成功返回 0,如果失败返回错误代码。

pthread_cond_broadcast 唤醒所有当前等待在 cond 条件变量上的线程。通常用于多个线程可能需要响应某个条件变化的场景。这些线程会尝试重新获得与条件变量关联的互斥锁,并在锁定成功后继续执行。

cp问题

生产者 VS 生产者 : 竞争关系,互斥关系

生产者 VS 消费者 :互斥关系,原子性。同步。

消费者 VS 消费者 : 互斥关系

3种关系,2种角色–生产者消费者,1个消费场所–特定结构的内存空间

优点:支持忙闲不均。生产与消费进行解耦。

伪唤醒

在生产消费者模型下,队列还剩余一个被生产满,刚好这时唤醒了一批线程,其中一个抢到了锁,并将队列生产满,释放锁之后,这个锁又刚好被上次唤醒的线程抢到,又要去执行生产任务,但是队列是满的,所以就发生了伪唤醒的情况。

信号量

POSIX信号量和SystemV信号量作用相同,都是用于同步操作,达到无冲突的访问共享资源目的。 但POSIX可以用于线程间同步。

//始化信号量
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
//参数:
//pshared:0表示线程间共享,非零表示进程间共享
//value:信号量初始值//销毁信号量
int sem_destroy(sem_t *sem);//等待信号量
//功能:等待信号量,会将信号量的值减1
int sem_wait(sem_t *sem); //P()//发布信号量
//功能:发布信号量,表示资源使用完毕,可以归还资源了。将信号量值加1。
int sem_post(sem_t *sem);//V()

基于环形队列的生产消费者模型:

在这里插入图片描述

多线程的互斥用信号量

信号量可以用于控制多个线程对共享资源的访问,尤其是在需要限制并发数量的场合。比如,使用计数信号量可以允许一定数量的线程同时访问资源,从而实现并发控制。

单线程的互斥用锁

锁(如互斥锁)适合于保护共享资源的独占访问,确保在任何时刻只有一个线程能够进入临界区。单线程的情况下,锁的使用更为简单和直接,因为不需要管理并发访问的复杂性。

  • 信号量适用于多线程环境下的资源计数和控制,并发访问。
  • 更适合于需要独占访问的情境,确保数据一致性。
    可以允许一定数量的线程同时访问资源,从而实现并发控制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/452708.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Cesium 影像加载的TileReplacementQueue技术

本文以分析QuadtreePrimitive及相关影像内容&#xff0c;讨论一些流程和方法。影像和地形是Cesium的基础内容&#xff0c;但是有时候感觉这部分的加载和渲染效率并不高。 TileReplacementQueue是一个非常神奇的类&#xff0c;我自己研究了小半天。虽然结构简单&#xff0c;但是…

ACH支付详解,北美电商为何偏爱这一方式

ACH支付在北美广泛应用&#xff0c;低成本、可逆、安全、便捷。ZohoBooks财务管理软件支持ACH&#xff0c;可自动化处理收付款&#xff0c;提高效率并减少错误。适合北美电商客户使用&#xff0c;支持多货币和税务法规。 一、什么是ACH支付&#xff1f; ACH支付是一种通过名为…

②PROFINET转ModbusTCP, EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关

EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关https://item.taobao.com/item.htm?ftt&id822721028899 协议转换通信网关 PROFINET 转 Modbus TCP &#xff08;接上一章&#xff09; 配置使用 与 PROFINET 主站进行组态说明 这里介绍与西门子 PLC 的…

大数据-180 Elasticsearch - 原理剖析 索引写入与近实时搜索

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

Docker-Consul概述以及集群环境搭建

文章目录 一、Docker consul概述二、consul 部署1.consul服务器2.registrator服务器&#xff08;客户端&#xff09;2.consul-template&#xff08;在consul服务器&#xff09;3.consul 多节点 一、Docker consul概述 容器服务更新与发现&#xff1a;先发现再更新&#xff0c;…

leetcode289:生命游戏

根据 百度百科 &#xff0c; 生命游戏 &#xff0c;简称为 生命 &#xff0c;是英国数学家约翰何顿康威在 1970 年发明的细胞自动机。 给定一个包含 m n 个格子的面板&#xff0c;每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态&#xff1a; 1 即为 活细胞 &am…

ClickFix攻击活动升级:可通过虚假谷歌会议画面传播恶意软件

最近&#xff0c;研究人员报告了一种新的 ClickFix 攻击活动&#xff0c;主要通过诱骗用户访问显示虚假连接错误的欺诈性 谷歌会议的页面&#xff0c;继而借此传播信息窃取恶意软件&#xff0c;主要针对 Windows 和 macOS 操作系统。 ClickFix是网络安全公司Proofpoint在5月份…

016集——c# 实现CAD类库 与窗体的交互(CAD—C#二次开发入门)

第一步&#xff1a;搭建CAD类库dll开发环境。 第二步&#xff1a;添加窗体 第三步&#xff1a;添加控件 第四步&#xff1a;双击控件&#xff0c;在控件点击方法内输入代码 第五步&#xff1a;在主程序内实例化新建的form类&#xff0c;并弹窗form窗体 第六步&#xff1a;CAD命…

第五届人工智能与教育国际学术会议(ICAIE 2024)

文章目录 一、会议详情二、重要信息三、大会介绍四、出席嘉宾五、征稿主题六、咨询 一、会议详情 二、重要信息 大会官网&#xff1a;https://ais.cn/u/vEbMBz提交检索&#xff1a;EI Compendex、IEEE Xplore、Scopus 三、大会介绍 第五届人工智能与教育国际学术会议&#x…

学习虚幻C++开发日志——TSet

TSet 官方文档&#xff1a;虚幻引擎中的Set容器 | 虚幻引擎 5.5 文档 | Epic Developer Community (epicgames.com) TSet 是通过对元素求值的可覆盖函数&#xff0c;使用数据值本身作为键&#xff0c;而不是将数据值与独立的键相关联。 默认情况下&#xff0c;TSet 不支持重…

大数据-168 Elasticsearch 单机云服务器部署运行 详细流程

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

基于stm32的4G模块点灯实验

led模块功能封装 #include "led.h" #include "sys.h"//初始化GPIO函数 void led_init(void) {GPIO_InitTypeDef gpio_initstruct;//打开时钟__HAL_RCC_GPIOB_CLK_ENABLE();//调用GPIO初始化函数gpio_initstruct.Pin GPIO_PIN_8 | GPIO_PIN_9;gpio_inits…

Linux基本指令一眼看懂(简洁表示)

首先先声明是简单表示&#xff0c;如果要全指令有链接 1. ls 指令 ls [选项] [文件/目录]常用选项: -l: 以长格式列出文件和目录的详细信息。 -a: 显示所有文件&#xff0c;包括隐藏文件&#xff08;以.开头的文件&#xff09;。 -h: 以人类可读的格式显示文件大小。 示例: …

基于stm32的esp8266的WIFI控制风扇实验

实验案例&#xff37;&#xff29;&#xff26;&#xff29;控制风扇 项目需求 电脑通过esp8266模块远程遥控风扇。 项目框图 ​ 风扇模块封装 #include "sys.h" #include "fan.h"void fan_init(void) {GPIO_InitTypeDef gpio_initstruct;//打开时钟…

数据库知识点整理

DDL DDL-数据库操作 show databases ------------ 查看所有数据库 select database(); ----------查看当前数据库 create database 数据库名&#xff1b;---- 创建数据库 use 数据库名&#xff1b; --------------使用数据库 drop database 数据库名&#xff1b;--…

day02_计算机常识丶第一个程序丶注释丶关键字丶标识符

计算机常识 计算机如何存储数据 计算机世界中只有二进制。那么在计算机中存储和运算的所有数据都要转为二进制。包括数字、字符、图片、声音、视频等。 进制 进制也就是进位计数制&#xff0c;是人为定义的带进位的计数方法 实例&#xff1a; // 在java 中 可以使用不同…

[PHP]Undefined index错误只针对数组

1、示例一 <?php $a null; var_dump($a[name]); 结果&#xff1a;无报错 2、示例二 <?php $a []; var_dump($a[name]);结果&#xff1a;报错

【JavaEE初阶】深入理解网络编程—使用UDP协议API实现回显服务器

前言 &#x1f31f;&#x1f31f;本期讲解关于TCP/UDP协议的原理理解~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不…

JMeter 中两大高级线程组的区别与应用

一、JMeter 中的高级线程组概述 最近群里的测试小伙伴在问在 JMeter 中&#xff0c;“jpgc - Ultimate Thread Group”和“jpgc - Stepping Thread Group 阶梯加压”有哪些区别和实际应用场景有哪些&#xff1f;所以这里也跟大家分享一下 JMeter 作为一款强大的性能测试工具&a…

Java项目-基于Springboot的应急救援物资管理系统项目(源码+说明).zip

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…