线程条件控制实现线程的同步

news2024/11/27 11:42:10

        前面讲了互斥锁,但是总感觉有些功能互斥锁有些不够用。

    条件变量是线程另一可用的同步机制。条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生。

  条件本身是由互斥量保护的。线程在改变条件状态前必须首先锁住互斥量,其他线程在获得互斥量之前不会察觉到这种改变,因为必须锁定互斥量以后才能计算条件。

条件创建

  条件变量使用之前必须首先初始化,pthread_cond_t数据类型代表的条件变量可以用两种方式进行初始化,可以把常量PTHREAD_COND_INITIALIZER赋给静态分配的条件变量,但是如果条件变量是动态分配的,可以使用pthread_cond_destroy函数对条件变量进行去除初始化。

函数原型

int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);

参数

pthread_cond_t *restrict cond:条件的地址

const pthread_condattr_t *restrict attr:条件的参数,一般为NULL就可以

返回值

若成功返回0,否则返回错误编号

条件销毁

函数原型

int pthread_cond_destroy(pthread_cond_t *cond);

参数

pthread_cond_t *restrict cond:条件的地址

返回值

若成功返回0,否则返回错误编号

条件触发

这两个函数可以用于通知线程条件已经满足。pthread_cond_signal函数将唤醒等待该条件的某个线程,而pthread_cond_broadcast函数将唤醒等待该条件的所有进程。

注意一定要在改变条件状态以后再给线程发信号。

函数原型

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);

返回值

若成功返回0,否则返回错误编号

条件等待

pthread_cond_wait等待条件变为真。如果在给定的时间内条件不能满足,那么会生成一个代表一个出错码的返回变量。传递给pthread_cond_wait的互斥量对条件进行保护,调用者把锁住的互斥量传给函数。函数把调用线程放到等待条件的线程列表上,然后对互斥量解锁,这两个操作都是原子操作。这样就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道,这样线程就不会错过条件的任何变化。pthread_cond_wait返回时,互斥量再次被锁住。

函数原型

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);

参数

pthread_cond_t *restrict cond:条件的地址

pthread_mutex_t *restrict mutex:互斥锁的地址

cond struct timespec *restrict timeout:timeout指定了等待的时间,它是通过timespec结果指定。

返回值

若成功返回0,否则返回错误编号

示例:

当 t2 线程将g_data加到3时,t1 线程才开始运行。

#include <stdio.h>
#include <pthread.h>
//int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); 
//int pthread_mutex_destroy(pthread_mutex_t mutex);
//int pthread_mutex_lock(pthread_mutex_t mutex);
//int pthread_mutex_trylock(pthread_mutex_t mutex);
//int pthread_mutex_unlock(pthread_mutex_t mutex)
//int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
//int pthread_cond_destroy(pthread_cond_t cond);
//int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
//int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);
//int pthread_cond_signal(pthread_cond_t cond);
//int pthread_cond_broadcast(pthread_cond_t cond);

pthread_mutex_t mutex;
pthread_cond_t cond;
int g_data=0;

void *func1(void *arg)
{
        printf("t1:%ld thread is creart\n",(unsigned long)pthread_self());
        printf("t1:param is %d\n",*((int *)arg));
        pthread_mutex_lock(&mutex);
        while(1)
        {
                pthread_cond_wait(&cond,&mutex);
                if(g_data==3)
                {
                        printf("ti run==================\n");
                }
                printf("t1:%d\n",g_data);
                g_data=0;
                sleep(1);

        }

}

void *func2(void *arg)
{
        printf("t2:%ld thread is creart\n",(unsigned long)pthread_self());
        printf("t2:param is %d\n",*((int *)arg));
        while(1)
        {
                printf("t2:%d\n",g_data);
                pthread_mutex_lock(&mutex);
                g_data++;
                if(g_data ==3 )
                {
                        pthread_cond_signal(&cond);
                }
                pthread_mutex_unlock(&mutex);
                sleep(1);
        }
}

int main()
{
        int param=100;
        char *pret=NULL;
        int ret1;
        int ret2;
        pthread_t t1;
        pthread_t t2;

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

        ret1=pthread_create(&t1, NULL,func1, (void *)&param);
        ret2=pthread_create(&t1, NULL,func2, (void *)&param);
        if(ret1 == 0)
        {
                printf("main:create t1 successed\n");
        }

        if(ret2 == 0)
        {
                printf("main:create t2 successed\n");
        }


        pthread_join(t1,NULL);
        pthread_join(t2,NULL);

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

可以看到以上代码,只要g_data加到3 就运行t1线程,并把g_data置为0,然后退出t1线程。

以上代码用的都是条件、互斥锁的动态初始化 pthread_cond_init(&cond,NULL); pthread_mutex_init(&mutex,NULL);,还可以使用宏来进行静态初始化 pthread_cond_t = PTHREAD_INITIALIZER; pthread_mutex_t = PTHREAD_MUTEX_INITIALIZER;

PS代码测试技巧

int main(int argc ,char **argv)
{

        int i;
        int cnt=atoi(argv[1]);
        for(i=0;i<cnt;i++)
        {
                system("./test");
        }
        return 0;
}

./a.out 10 >> test.ret.txt &
等测试完毕后可以在test.ret.txt里查看测试的结果,&代表的是后台运行。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习

&#x1f9f8;欢迎来到dream_ready的博客&#xff0c;&#x1f4dc;相信您对这几篇博客也感兴趣o (ˉ▽ˉ&#xff1b;) &#x1f4dc;什么是SpringMVC&#xff1f;简单好理解&#xff01;什么是应用分层&#xff1f;SpringMVC与应用分层的关系&#xff1f; 什么是三层架构&…

Danswer 接入 Llama 2 模型 | 免费在 Google Colab 上托管 Llama 2 API

一、前言 前面在介绍本地部署免费开源的知识库方案时&#xff0c;已经简单介绍过 Danswer《Danswer 快速指南&#xff1a;不到15分钟打造您的企业级开源知识问答系统》&#xff0c;它支持即插即用不同的 LLM 模型&#xff0c;可以很方便的将本地知识文档通过不同的连接器接入到…

Linux中的高级IO

文章目录 1.IO1.1基本介绍1.2基础io的低效性1.3如何提高IO效率1.4五种IO模型1.5非阻塞模式的设置 2.IO多路转接之Select2.1函数的基本了解2.2fd_set理解2.3完整例子代码&#xff08;会在代码中进行讲解&#xff09;2.4优缺点 3.多路转接之poll3.1poll函数的介绍3.2poll服务器3.…

初阶JavaEE(15)(Cookie 和 Session、理解会话机制 (Session)、实现用户登录网页、上传文件网页、常用的代码片段)

接上次博客&#xff1a;初阶JavaEE&#xff08;14&#xff09;表白墙程序-CSDN博客 Cookie 和 Session 你还记得我们之前提到的Cookie吗&#xff1f; Cookie是HTTP请求header中的一个属性&#xff0c;是一种用于在浏览器和服务器之间持久存储数据的机制&#xff0c;允许网站…

【51单片机】蜂鸣器(学习笔记)

一、蜂鸣器 1、蜂鸣器介绍 鸣器是一种将电信号转换为声音信号的器件&#xff0c;常用来产生设备的按键音、报警音等提示信号 有源蜂鸣器&#xff1a;内部自带振荡源&#xff0c;将正负极接上直流电压即可持续发声&#xff0c;频率固定无源蜂鸣器&#xff1a;内部不带振荡源&…

Educational Codeforces Round 157 (Rated for Div. 2) F. Fancy Arrays(容斥+组合数学)

题目 称一个长为n的数列a是fancy的&#xff0c;当且仅当&#xff1a; 1. 数组内至少有一个元素在[x,xk-1]之间 2. 相邻项的差的绝对值不超过k&#xff0c;即 t(t<50)组样例&#xff0c;每次给定n(1<n<1e9),x(1<x<40), 求fancy的数组的数量&#xff0c;答案…

【错误解决方案】ModuleNotFoundError: No module named ‘my_fake_useragent‘

1. 错误提示 ModuleNotFoundError: No module named my_fake_useragent&#xff0c;这意味着你试图导入一个名为 my_fake_useragent 的模块&#xff0c;但Python找不到这个模块。 2. 解决方案 检查模块名是否正确: 确保你试图导入的模块名是正确的。也许你拼写错误或者大小写不…

NeurIPS 2023 | 基于多模态统一表达的跨模态泛化

©PaperWeekly 原创 作者 | 夏炎 学校 | 浙江大学 研究方向 | 多模态 论文标题&#xff1a; Achieving Cross Modal Generalization with Multimodal Unified Representation 模型&代码地址&#xff1a; https://github.com/haihuangcode/CMG 在本文中&#xff0c;我们…

LeetCode 面试题 16.17. 连续数列

文章目录 一、题目二、C# 题解 一、题目 给定一个整数数组&#xff0c;找出总和最大的连续数列&#xff0c;并返回总和。 示例&#xff1a; 输入&#xff1a; [-2,1,-3,4,-1,2,1,-5,4] 输出&#xff1a; 6 解释&#xff1a; 连续子数组 [4,-1,2,1] 的和最大&#xff0c;为 6。…

树结构及其算法-线索二叉树

目录 树结构及其算法-线索二叉树 C代码 树结构及其算法-线索二叉树 虽然我们把树转换为二叉树可减少空间的浪费——由2/3降低到1/2&#xff0c;但是如果仔细观察之前使用链表建立的n节点二叉树&#xff0c;那么会发现用来指向左右两个节点的指针只有n-1个链接&#xff0c;另…

如何快速导出、备份微信通讯录好友联系人微信号

6-9 如果因工作需要&#xff0c;你有多个微信&#xff0c;并且你的业务开发的客户都在这些微信里&#xff0c;将会面临一个问题&#xff0c;那就是备份问题&#xff0c;因为通过微信做业务&#xff0c;如果遇到微信不小心被封号&#xff0c;或者离职的交接等情况&#xff0c;客…

【Mybatis小白从0到90%精讲】03:编写Mapper,第一个入门程序

文章目录 前言一、创建mysql user表二、注解方式三、XML方式四、编写main方法调用前言 映射器Mapper是 MyBatis 中最重要的文件,简单的讲主要用来映射SQL语句。 映射器有两种实现方式:注解方式、XML文件方式(推荐)。 接下来演示通过两种方式,开发Mybatis第一个入门程序,…

GEE数据集——2019、2020、2021、2022和2023年全球固定宽带和移动(蜂窝)网络性能Shapefile 格式数据集

全球固定宽带和移动&#xff08;蜂窝&#xff09;网络性能 全球固定宽带和移动&#xff08;蜂窝&#xff09;网络性能&#xff0c;分配给缩放级别 16 网络墨卡托图块&#xff08;赤道处约 610.8 米 x 610.8 米&#xff09;。数据以 Shapefile 格式和 Apache Parquet 格式提供&…

安装MySQL时出现 由于找不到 MSVCR120.dll,无法继续执行代码。重新安装程序可能会解决此问题。

--------------------------- mysqld.exe - 系统错误 --------------------------- 由于找不到 MSVCR120.dll&#xff0c;无法继续执行代码。重新安装程序可能会解决此问题。 --------------------------- 确定 --------------------------- 安装MySQL时出现 “This appl…

C语言实现九九乘法表

学习C语言后&#xff0c;我们会发现打印九九乘法表是很简单的&#xff0c;话不多说&#xff0c;我们上代码&#xff01; 目录 1.函数代码 2.运行结果 1.函数代码 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() {int i 1;int j 1;int n 0;//行数in…

麒麟系统 UFW 操作文档

麒麟系统 UFW 操作文档 1. UFW 介绍 ufw&#xff08;简单防火墙 Uncomplicated FireWall&#xff09;真正地简化了 iptables&#xff0c;虽然 ufw 的底层依 然会调用 iptables&#xff0c;但是配置防火墙规则时操作更加方便&#xff0c;命令更加简洁&#xff0c;本文档主要介…

49基于matlab的Non dominated sorting genetic algorithm -II(NSGA-Ⅱ)多目标遗传算法

基于matlab的Non dominated sorting genetic algorithm -II&#xff08;NSGA-Ⅱ&#xff09;多目标遗传算法&#xff0c;其优势是降低了非劣排序遗传算法的复杂性&#xff0c;具有运行速度快&#xff0c;解集的收敛性好的优点&#xff0c;成为其他多目标优化算法性能的基准。程…

Python自定义函数练习(持续更新中~)

1.计算矩阵的面积和周长&#xff1a; class Rectangle:def __init__(self, width, height):self.width widthself.height heightdef area(self):return self.width * self.heightdef perimeter(self):return 2 * (self.width self.height)if __name__ "__main__"…

Ubuntu网络IP地址一直显示127.0.0.1

问题描述&#xff1a; 终端输入ip a显示127.0.0.1&#xff0c;原来类似192.168.231.1的地址不见了。 ip a 点击网络配置&#xff08;ubuntu桌面版&#xff09;&#xff0c;发现无线网络模块看不见了 正常情况应该有wired 模块&#xff0c;就是下面标红的 解决方案&#xff1a…

c语言实现http下载功能,显示进度条和下载速率

#include <stdio.h>//printf #include <string.h>//字符串处理 #include <sys/socket.h>//套接字 #include <arpa/inet.h>//ip地址处理 #include <fcntl.h>//open系统调用 #include <unistd.h>//write系统调用 #include <netdb.h>//…