Linux-线程同步

文章目录

  • 前言
  • 一、为什么要线程同步?
  • 二、线程同步
    • pthread_cond_init
    • pthread_cond_destroy
    • pthread_cond_wait、pthread_cond_signal和 pthread_cond_broadcast
  • 三、示例代码


前言

上节课学习了线程互斥,这节课针对线程互斥内容在做进一步的补充和完善,学习线程同步的概念。


提示:以下是本篇文章正文内容,下面案例可供参考

一、为什么要线程同步?

上一章我们所讲的线程互斥有一个问题,虽然我们有互斥锁,但是当我们的临界资源条件不满足时,我们就需要不断重复申请锁和释放锁的过程,做无用功,浪费系统和cpu资源,所以,针对此问题,我们就引入了线程同步来解决。

线程同步其本质就是告诉其他线程什么时候我们的临界资源已经准备就绪,可以开始运行,如果没有准备就绪,那么就阻塞。 这样就能很大程度上节约我们的系统资源。

二、线程同步

pthread_cond_init

man 3 pthread_cond_init
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

该函数与pthread_mutex_init 使用类似,当pthread_cond是全局或静态变量时,可以使用PTHREAD_COND_INITIALIZER来进行初始化。

pthread_cond_destroy

该函数与pthread_mutex_init 使用类似,当pthread_cond是全局或静态变量时,不需要调用此函数进行销毁。

pthread_cond_wait、pthread_cond_signal和 pthread_cond_broadcast

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex)

#include <pthread.h>
int pthread_cond_broadcast(pthread_cond_t *cond); int pthread_cond_signal(pthread_cond_t *cond);

pthread_cond_signal和 pthread_cond_broadcast 这两个函数都是用与告诉需要被同步的线程:条件已经满足,(你)你们可以运行了。
它们俩的区别就是,pthread_cond_signal一次只能一个线程可以运行,而pthread_cond_broadcast则是可以一次若干个线程按次序运行。

pthread_cond_wait函数是用于判断条件是否满足,如果不满足,则阻塞。

三、示例代码

需要注意的是,cond也要配合mutex来进行使用,他们两个是很有关联的。
代码如下(示例):

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstdio>

#define TNUM 5

volatile bool quit = false; //防止编译器过度优化

typedef void (*Func_t)(std::string, pthread_mutex_t *, pthread_cond_t *);

void ThreadFunc1(std::string name, pthread_mutex_t *mutex, pthread_cond_t *cond)
{
    while (!quit)
    {
        pthread_mutex_lock(mutex);
        pthread_cond_wait(cond, mutex);
        if (!quit/*临界资源条件判断*/)
            std::cout << name << ": 查看 " << std::endl;
        pthread_mutex_unlock(mutex);
    }
}

void ThreadFunc2(std::string name, pthread_mutex_t *mutex, pthread_cond_t *cond)
{
    while (!quit)
    {
        pthread_mutex_lock(mutex);
        pthread_cond_wait(cond, mutex);
        if (!quit/*临界资源条件判断*/)
            std::cout << name << ": 保存 " << std::endl;
        pthread_mutex_unlock(mutex);
    }
}

void ThreadFunc3(std::string name, pthread_mutex_t *mutex, pthread_cond_t *cond)
{
    while (!quit)
    {
        pthread_mutex_lock(mutex);
        pthread_cond_wait(cond, mutex);
        if (!quit/*临界资源条件判断*/)
            std::cout << name << ": 读取 " << std::endl;
        pthread_mutex_unlock(mutex);
    }
}

void ThreadFunc4(std::string name, pthread_mutex_t *mutex, pthread_cond_t *cond)
{
    while (!quit)
    {
        pthread_mutex_lock(mutex);
        pthread_cond_wait(cond, mutex);
        if (!quit/*临界资源条件判断*/)
            std::cout << name << ": 打印 " << std::endl;
        pthread_mutex_unlock(mutex);
    }
}

void ThreadFunc5(std::string name, pthread_mutex_t *mutex, pthread_cond_t *cond)
{
    while (!quit)
    {
        pthread_mutex_lock(mutex);
        pthread_cond_wait(cond, mutex);
        if (!quit/*临界资源条件判断*/)
            std::cout << name << ": 切换 " << std::endl;
        pthread_mutex_unlock(mutex);
    }
}

class Data
{
public:
    Data(std::string name, Func_t func, pthread_mutex_t *mutex, pthread_cond_t *cond)
        : _name(name), _func(func), _mutex(mutex), _cond(cond)
    {
    }

public:
    std::string _name;
    Func_t _func;
    pthread_mutex_t *_mutex;
    pthread_cond_t *_cond;
};

void *Total(void *args)
{
    Data *cont = (Data *)args;
    cont->_func(cont->_name, cont->_mutex, cont->_cond);
    delete cont;
    return nullptr;
}

int main()
{
    pthread_mutex_t mutex;
    pthread_cond_t cond;

    pthread_mutex_init(&mutex, nullptr);
    pthread_cond_init(&cond, nullptr);

    pthread_t tids[TNUM];
    Func_t funcs[TNUM] = {ThreadFunc1, ThreadFunc2, ThreadFunc3, ThreadFunc4, ThreadFunc5};
    for (int i = 0; i < TNUM; i++)
    {
        std::string name = "New thread ";
        name += std::to_string(i + 1);
        Data *cont = new Data(name, funcs[i], &mutex, &cond);
        pthread_create(tids + i, nullptr, Total, (void *)cont);
    }

    int count = 10;

    sleep(5);

    while (count)
    {
        std::cout << "conut : " << count-- << " -----------" << std::endl;
        pthread_cond_signal(&cond);
        // pthread_cond_broadcast(&cond);
        sleep(1);
    }

    quit = true;
    pthread_cond_broadcast(&cond);

    for (int i = 0; i < TNUM; i++)
    {
        pthread_join(tids[1], nullptr);
        std::cout << "New thread " << i + 1 << " has quit." << std::endl;
    }

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}


在这里插入图片描述


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙Harmony应用开发—ArkTS(@State装饰器:组件内状态)

State装饰的变量&#xff0c;或称为状态变量&#xff0c;一旦变量拥有了状态属性&#xff0c;就和自定义组件的渲染绑定起来。当状态改变时&#xff0c;UI会发生对应的渲染改变。 在状态变量相关装饰器中&#xff0c;State是最基础的&#xff0c;使变量拥有状态属性的装饰器&a…

Elasticsearch:让你的 Elasticsearch 索引与 Python 和 Google Cloud Platform 功能保持同步

作者&#xff1a;来自 Elastic Garson Elasticsearch 内的索引 (index) 是你可以将数据存储在文档中的位置。 在使用索引时&#xff0c;如果你使用的是动态数据集&#xff0c;数据可能会很快变旧。 为了避免此问题&#xff0c;你可以创建一个 Python 脚本来更新索引&#xff0…

VMWare虚拟机使用openmediavault搭建NAS服务器完整步聚

下载: gopenmediavault - The open network attached storage solution 下载好openmediavault的ISO镜像后,打开虚拟机并安装 系统类型选择Debian 启动虚拟机并安装openmediavault 选择中文 地区选中国 键盘配置选汉语 开始安装 配置网络信息 配置root密码 确认密码 系统安装中…

LeetCode # 199. 二叉树的右视图

199. 二叉树的右视图 题目 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4] 示例 2: 输入: [1,null,3] 输出: [1,3] 示例 3…

最新域名出售交易平台源码修复版

最新域名出售交易平台源码修复版 测试正常分享&#xff0c;保障你使用愉快&#xff0c;源码测试修复不易&#xff0c;拿走留痕是美德 无需到处找教程或修复&#xff0c;教程一次性到位&#xff0c;无需藏着掖着 最新修复版域名出售交易平台源码&#xff0c;搭建即可正常使用…

【群晖】Docker Compose部署 Emby Server

【群晖】Docker Compose部署 Emby Server 本来群晖上面的 Emby 是用套件安装的&#xff0c;但是不巧的是前两天脑袋一抽装了两个插件&#xff0c;导致 Emby Server被当肉鸡了&#xff0c;还找不到脚本代码在哪儿&#xff0c;一天时间上传了3T的流量。无奈之下&#xff0c;只能尝…

头条网盘拉新项目该怎么选择授权

作为十二月份首发上线的项目——头条网盘拉新。一经上线就受到很多想要做这行业人的关注&#xff0c;光是佣金已经是业内比较高的了&#xff01;每拉新一位新用户就可以获取到价格为9元一单的佣金&#xff0c;拉失活用户也可以获取价格为4元的佣金&#xff0c;推广方式和其他网…

真机笔记(2)项目分析

目录 1. 项目&#xff1a; 2. 网络工程师工作流程 3. 实验 设备命名 登录密码 使用SSH协议 1. 项目&#xff1a; 竞标方&#xff1a;集成商、厂商、代理商、服务商、监理检测公司 在一个网络项目中&#xff0c;不同的角色承担着不同的职责和任务。以下是集成商、厂商、代…

JavaScript-Web学习笔记01

一、Web APIs 1、Web API Web API 是浏览器提供的一套操作浏览器功能和页面元素的API&#xff08;BOM 和 DOM&#xff09;。 2、总结 API 是为我们提供的一个接口&#xff0c;帮助我们实现某种功能Web API 主要是针对浏览器提供的接口&#xff0c;主要针对浏览器做交互效果。W…

腾讯云COS - 前端上传文件到 COS 跨域问题

问题描述 原因分析 因为我本地的地址是&#xff1a;http://localhost:9528 而发送请求时的地址是&#xff1a;http://132-1307119153.cos.ap-beijing.myqcloud.com/tu.jpg 域名不同&#xff0c;自然而然就出现了跨域的问题&#xff01; 解决方案 先点击对象存储 - 安全设置…

吃瓜Grok大模型

段子区 今年当地时间2月29日晚&#xff0c;马斯克闹出来一件大事——正式起诉OpenAI和Sam Altman&#xff0c;并要求OpenAI 恢复开源GPT-4等模型。国际流量大师我只付服马斯克和川宝!&#xff01; 当大家觉得这扯皮的故事就此结束后&#xff0c;马斯克“不负众望”的整了一个大…

算法-图的强连通分量,图的最小生成树

1.图的强连通分量 (1). 定义 图的强连通分量是图论中的一个重要概念&#xff0c;主要在有向图中进行讨论。具体来说&#xff0c;如果在一个有向图G中&#xff0c;任意两个顶点vi和vj&#xff08;其中vi大于vj&#xff09;之间都存在一条从vi到vj的有向路径&#xff0c;同时也存…

解锁AI之门:协助探索Amazon Bedrock服务

AI愈加强大的功能和广泛的应用场景&#xff0c;正逐渐改变着我们的工作和生活方式。 Amazon Bedrock在AI的时代潮流中&#xff0c;也以其强大而灵活的功能特性&#xff0c;正在成为越来越多企业和个人的智能助手。 亚马逊云科技通过VERYCLOUD睿鸿股份的服务能力&#xff0c;使…

PyTorch深度学习:如何提升遥感影像的地物分类精度?

我国高分辨率对地观测系统重大专项已全面启动&#xff0c;高空间、高光谱、高时间分辨率和宽地面覆盖于一体的全球天空地一体化立体对地观测网逐步形成&#xff0c;将成为保障国家安全的基础性和战略性资源。未来10年全球每天获取的观测数据将超过10PB&#xff0c;遥感大数据时…

F. Microcycle(dfs 搜寻路径 + 并查集)

解析&#xff1a; 本题的意思是&#xff0c;求一个环的最小的那条边。 并且输出其这个环的点。 我们可以利用并查集&#xff0c;进行确定其是否有环路。在将所用的边从大到小排序。 利用 vector容器&#xff0c;pop_back() 和 push的特性。 起点为 u终点为 v寻找路径。 代…

P2789 直线交点数题解

题目 假设平面上有N条直线&#xff0c;且无三线共点&#xff0c;那么这些直线一共能有多少不同的交点数&#xff1f; 输入输出格式 输入格式 一行&#xff0c;一个整数N&#xff0c;代表有N条直线。 输出格式 一行&#xff0c;一个整数&#xff0c;表示方案总数。 输入输…

金融知识分享系列之:出场信号RSI指标

金融知识分享系列之&#xff1a;出场信号RSI指标 一、出场信号RSI指标二、RSI指标原理三、 指标用法四、RSI指标总结 一、出场信号RSI指标 名称&#xff1a;相对强弱指标参数&#xff1a;(默认14)组成&#xff1a;RSI线以及30轴、50轴、70轴构成 0-30是极弱&#xff1a;0-30的…

天天爱掼蛋规则

一、牌型 1、单张&#xff1a;任意一张单牌&#xff1b; 2、对子&#xff1a;任意两张点数相同的牌&#xff0c;如33、44&#xff1b; 3、三同张&#xff1a;三张牌点相同的牌型&#xff0c;如555&#xff1b; 4、三同连张&#xff08;也叫钢板&#xff09;&#xff1a;两组…

蓝桥杯单片机快速开发笔记——特训2 按键的长按与短按

一、题目要求 在CT107D单片机综合训练平台上&#xff0c;通过I/O模式编写代码&#xff0c;实现以下功能&#xff1a; 系统上电后&#xff0c;关闭蜂鸣器、继电器和全部指示灯&#xff0c;数码管显示初始值为28&#xff0c;仅显示数码管最右边两位。利用定时器0实现10ms间隔定…

分享基于PDF.js的pdf阅读器代码

一、前言 有时候开发PC端web页面的时候会遇到PDF预览、下载等功能&#xff0c;为了兼容浏览器&#xff0c;需要找一款前端插件进行开发。比较好的PDF插件&#xff0c;就是mozilla的pdf.js&#xff08;注意是mozilla&#xff0c;如果你百度遇到需要收费的&#xff0c;那应该是下…