当前位置: 首页 > news >正文

【Linix-Day12-线程同步和线程安全】

线程同步 和 线程安全

线程同步

除了信号量和互斥锁(互斥锁和条件变量上次介绍过),还有两种方式同步

1.读写锁

当同时对一块内存读写时,会出现下列问题,故而引入读写锁

在这里插入图片描述

接口介绍:

1.int pthread_rwlock_init(pthread_rwlock_t *rwlock, pthread_rwlockattr_t *attr);

函数功能:初始化读写锁

rwlock :传入定义的读写锁地址

attr : 读写锁的属性,一般默认为 NULL

返回值:如果成功,函数应返回零

2.int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

函数功能:加读锁,其他线程无法写入

rwlock :传入定义的读写锁地址

3.int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

函数功能:加写锁,其他线程无法写入,读取

rwlock :传入定义的读写锁地址

4.int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

函数功能:解锁,允许读和写

rwlock :传入定义的读写锁地址

5.int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

函数功能:销毁读写锁

rwlock :传入定义的读写锁地址

测试代码:

main.c

include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>pthread_rwlock_t rwlock;void *fun1(void *arg)
{for (int i = 0; i < 30; ++i){pthread_rwlock_rdlock(&rwlock);printf("fun1 read start\n");sleep(1);printf("fun1 read end\n");pthread_rwlock_unlock(&rwlock);sleep(1);}
}
void *fun2(void *arg)
{for (int i = 0; i < 10; ++i){pthread_rwlock_rdlock(&rwlock);printf("fun2 read start\n");sleep(3);printf("fun2 read end\n");pthread_rwlock_unlock(&rwlock);sleep(1);}
}
void *fun3(void *arg)
{for (int i = 0; i < 10; ++i){pthread_rwlock_wrlock(&rwlock);printf("fun3 write start\n");sleep(3);printf("fun3 write end\n");pthread_rwlock_unlock(&rwlock);sleep(1);}
}
int main()
{pthread_t id[3];pthread_rwlock_init(&rwlock, NULL);pthread_create(&id[0], NULL, fun1, NULL);pthread_create(&id[0], NULL, fun2, NULL);pthread_create(&id[0], NULL, fun3, NULL);for (int i = 0; i < 3; ++i){pthread_join(id[i], NULL);}pthread_rwlock_destroy(&rwlock);exit(0);
}

运行结果图:

2.条件变量

条件变量提供了一种线程间的通知机制:当某个共享数据达到某个值的时候,唤醒等待
这个共享数据的线程。

接口介绍:

1. int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr);

函数功能:初始化条件变量

cond:定义的条件变量的地址

attr:条件变量的属性,一般默认为 NULL

2. int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

函数功能:进入条件变量等待队列

cond:定义的条件变量的地址

mutex:定义的互斥锁的地址

3. int pthread_cond_signal(pthread_cond_t *cond);

函数功能: 唤醒单个线程

cond:定义的条件变量的地址

4. int pthread_cond_broadcast(pthread_cond_t *cond);

函数功能:唤醒所有等待的线程

cond:定义的条件变量的地址

5.int pthread_cond_destroy(pthread_cond_t *cond);

函数功能:摧毁条件变量

cond:定义的条件变量的地址

测试代码

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
pthread_cond_t cond;
pthread_mutex_t mutex;void *fun1(void *arg)
{char *s = (char *)arg;while (1){// 阻塞,被唤醒pthread_mutex_lock(&mutex);pthread_cond_wait(&cond, &mutex);pthread_mutex_unlock(&mutex);printf("fun1 read:%s\n", s);if (strncmp(s, "end", 3) == 0){break;}}
}
void *fun2(void *arg)
{char *s = (char *)arg;while (1){// 阻塞,被唤醒pthread_mutex_lock(&mutex);pthread_cond_wait(&cond, &mutex);pthread_mutex_unlock(&mutex);printf("fun2 read:%s\n", s);if (strncmp(s,"end",3) == 0){break;}}
}int main()
{pthread_cond_init(&cond, NULL);pthread_mutex_init(&mutex, NULL);pthread_t id[2];char buff[256]={0};pthread_create(&id[0], NULL, fun1, (void*)buff);pthread_create(&id[1], NULL, fun2, (void*)buff);while(1){printf("input: ");fflush(stdout);fgets(buff,255,stdin);printf("\n");if(strncmp(buff,"end",3) == 0){pthread_cond_broadcast(&cond);break;}else{pthread_cond_signal(&cond);}sleep(1);}for(int i=0;i<2;++i){pthread_join(id[i],NULL);}pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);exit(0);
}

运行结果图

在这里插入图片描述

线程安全

在多线程运行的时候,不论线程的调度顺序怎样,最终的结果都是一样的、正确的。那么就说这些线程是安全的。
要保证线程安全需要做到:
1)对线程同步,保证同一时刻只有一个线程访问临界资源。
2)在多线程中使用线程安全的函数(可重入函数),所谓线程安全的函数指的是:如果一个函数能被多个线程同时调用且不发生竟态条件,则我们程它是线程安全的。

下面展示使用不安全的线程函数举例

实现在两个线程中分别打印 char buff[] = “a b c d e f g h i”; char buff[] = “1 2 3 4 5 6 7 8 9”;两个数组

测试代码

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>void *PthreadFun(void *arg)
{char buff[] = "a b c d e f g h i";char *p = strtok(buff, " ");while (p != NULL){printf("fun:: %c\n", *p);p = strtok(NULL, " ");sleep(1);}
}int main()
{pthread_t id;int res = pthread_create(&id, NULL, PthreadFun, NULL);assert(res == 0);char buff[] = "1 2 3 4 5 6 7 8 9";char *p = strtok(buff, " ");while (p != NULL){printf("main:: %c\n", *p);p = strtok(NULL, " ");sleep(1);}exit(0);
}

运行结果

这是因为strtok()是线程不安全函数,内部实现使用了全局变量或静态变量,所以不能同时处理不同的字符串。

解决方法,使用线程安全版的 strtok_r();

char *strtok_r(char *str, const char *delim, char **saveptr);

str : 数组

delim: 分隔符

saveptr:是指向char*变量的指针,用来维护连续解析相同字符串的调用

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>void *PthreadFun(void *arg)
{char *q = NULL;char buff[] = "a b c d e f g h i";char *p = strtok_r(buff, " ",&q);while (p != NULL){printf("fun:: %c\n", *p);p = strtok_r(NULL, " ",&q);sleep(1);}
}int main()
{pthread_t id;int res = pthread_create(&id, NULL, PthreadFun, NULL);assert(res == 0);char *q = NULL;char buff[] = "1 2 3 4 5 6 7 8 9";char *p = strtok_r(buff, " ",&q);while (p != NULL){printf("main:: %c\n", *p);p = strtok_r(NULL, " ",&q);sleep(1);}exit(0);
}

运行结果

相关文章:

【Linix-Day12-线程同步和线程安全】

线程同步 和 线程安全 线程同步 除了信号量和互斥锁&#xff08;互斥锁和条件变量上次介绍过&#xff09;&#xff0c;还有两种方式同步 1.读写锁 当同时对一块内存读写时&#xff0c;会出现下列问题&#xff0c;故而引入读写锁 接口介绍&#xff1a; 1.int pthread_rwloc…...

C++中使用嵌套循环遍历多维数组

C中使用嵌套循环遍历多维数组 一维数组&#xff1a;数组元素可以看做是一行数据。 二维数组&#xff1a;更像是一个表格&#xff0c;既有行数据又有列数据。 C没有提供二维数组类型&#xff0c;但用户可以创建每个元素本身都是数组的数组。例如&#xff0c;假设要存储 5 个城…...

linux入门---命名管道

如何创建命名管道 使用mkfifo函数就可以在程序里面创建管道文件&#xff0c;该函数的声明如下&#xff1a; 该函数需要两个参数&#xff0c;第一个参数表示要在哪个路径下创建管道文件并且这个路径得待上管道文件的名字&#xff0c;因为每个文件都有对应的权限&#xff0c;所…...

SpringBoot2.0入门(详细文档)

文章目录 Springboot是什么Springboot2.x依赖环境和版本新特性说明为什么学习Springboot从springboot优点来看从未来发展的趋势来看 开发环境Spring Boot开发环境搭建和项目启动jdk 的配置Spring Boot 工程的构建maven配置IDEA 快速构建maven 创建工程常用注解 完整代码 Spring…...

Aztec的隐私抽象:在尊重EVM合约开发习惯的情况下实现智能合约隐私

1. 引言 Aztec的架构&#xff0c;不同于当前“通过EVM兼容执行环境”所实现的区块链水平扩容趋势。Aztec内部笑称其构建的为首个非zkEVM协议。 Aztec专注于实现&#xff1a; 成为理解和需要智能合约隐私的开发者的终极解决方案。 Aztec为开发者提供构建隐私优先app所需的网…...

【Vue】详细介绍Vue项目的目录结构及各个核心文件的示例代码

Vue.js并没有严格的文件和目录结构要求&#xff0c;但一般情况下&#xff0c;我们的Vue项目目录结构如下&#xff1a; ├── node_modules/ # 项目依赖的 node 模块 ├── public/ # 公共资源目录 │ ├── favicon.ico # 网页图标 │ └──…...

【人大金仓】迁移MySql数据库到人大金仓,出现sys_config表重复

需要迁移的数据库中有张表名称为sys_config&#xff0c;查询的时候查询结果不符合我们的预期&#xff0c;经咨询金仓售后人员后得知和系统表重名… 解决问题方法如下&#xff1a; alter database [数据库名] set search_path to "$user", [模式名,&#xff08;可选&…...

linux内核进程间通信IPC----消息队列

消息队列&#xff1a;提供一种从一个进程向另一个进程发送一个数据块的方法。与FIFO相比&#xff0c;消息队列的优势在于&#xff0c;它独立于发送和接收进程而存在。 1.链表式结构组织&#xff0c;存放于内核。 2.通过队列标识来引用。 3.通过一个数据类型来索引指定的数据。 …...

PHP实现微信小程序状态检测(违规、暂停服务、维护中、正在修复)

实现原理 进入那些状态不正常的小程序会被重定向至一个Url&#xff0c;使用抓包软件抓取这个Url&#xff0c;剔除不必要参数&#xff0c;使用cURl函数请求网页获得HTML内容&#xff0c;根据内容解析出当前APPID的小程序的状态。 代码 <?php// 编码header(Content-type:ap…...

ubuntu在线直接升级

前几天VMware上安装了ubuntu&#xff0c;当时的内核版本支持(ipguard,加密软件)&#xff0c;后来ubuntu自动升级了linux内核&#xff0c;导致加入软件不支持&#xff0c;无法访问加密文件了。后来加密软件商更新了软件&#xff0c;但还是赶不上linux内核更新速度&#xff0c;还…...

学习笔记:卸载nav2 navigation2导航

nav2二进制文件安装 nav2导航安装方式分为二进制文件安装和源码方式安装&#xff0c;如果想用最快的方式跑通代码&#xff0c;推荐二进制安装&#xff0c;不用编译&#xff0c;没有缺少依赖编译失败的烦恼&#xff0c; 安装命令&#xff1a; sudo apt install ros-$ROS_DISTR…...

觉非科技数据闭环系列 | BEV感知研发实践

随着自动驾驶迈向量产场景&#xff0c;“BEV感知数据闭环”已成为新一代自动驾驶量产系统的核心架构。数据成为了至关重要的技术驱动力&#xff0c;发挥数据闭环的飞轮效应或将成为下半场从1到N的胜负关键。 觉非科技在此方面已进行了大量的研究工作&#xff0c;并在实际量产项…...

程序员情绪把控

文章目录 建议情绪 建议 保持稳定的情绪在工作中非常重要&#xff0c;以下是一些建议&#xff1a; 自我意识&#xff1a;保持对自己情绪的觉察和理解&#xff0c;了解自己的情绪状态和触发情绪的因素。通过自我反省和观察&#xff0c;你可以更好地管理和调节情绪。 健康生活方…...

弱监督目标检测:ALWOD: Active Learning for Weakly-Supervised Object Detection

论文作者&#xff1a;Yuting Wang,Velibor Ilic,Jiatong Li,Branislav Kisacanin,Vladimir Pavlovic 作者单位&#xff1a;Rutgers University;The Institute for Artificial Intelligence Research and Development of Serbia;Nvidia Corporation 论文链接&#xff1a;http:…...

驱动开发 day3

总结&#xff1a;自动创建设备节点udev的流程 1.如何创建节点 手动创建&#xff1a;mknod 地址 设备文件类型 主设备号 次设备号(0 - 255) 自动创建&#xff1a;devfs (创建节点的逻辑在内核 ---> 2.4版本以前使用) udev (创建节点的逻辑在应用层) mdev (轻量级的udev) 2.…...

许可license分析 第一章

许可分析是指对软件许可证进行详细的分析和评估&#xff0c;以了解组织内部对软件许可的需求和使用情况。通过许可分析&#xff0c;可以帮助组织更好地管理和优化软件许可证的使用。以下是一些可能的许可分析方法和步骤&#xff1a; 收集许可证信息&#xff1a;首先&#xff0c…...

Goby 漏洞发布|管家婆订货易在线商城 SelectImage.aspx 文件上传漏洞

漏洞名称&#xff1a;管家婆订货易在线商城 SelectImage.aspx 文件上传漏洞 English Name&#xff1a; GJP SelectImage.aspx file upload vulnerability CVSS core: 9.8 影响资产数&#xff1a;2617 漏洞描述&#xff1a; 任我行率先针对中小企业推出了管家婆进销存、财务…...

Android屏幕录制

这里使用Java语言编写实现&#xff0c;完整代码如下&#xff1a; 文件 AndroidMainfest.xml 的主要配置 <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"package"…...

实在智能牵手埃林哲,“TARS-RPA-Agent+云时通”双剑合璧共推企业数字化转型

近日&#xff0c;《数字中国建设整体布局规划》进一步明确了数字化发展的方向和节奏&#xff0c;对企业数字化建设提出了新要求。回看过去几十年&#xff0c;信息化建设如火如荼&#xff0c;各类IT系统如雨后春笋般涌现&#xff0c;系统的自动化操作及系统间数据交互共享等需求…...

拥有这个中文版CustomGPT,你也能定制自己的AI问答机器人

人工智能技术的快速发展为各行各业带来了前所未有的机会&#xff0c;其中之一就是定制化的问答机器人。这些机器人可以用于客户支持、知识管理、虚拟助手等多个领域&#xff0c;帮助企业提高效率&#xff0c;提供更好的用户体验。很多人可能都知道通过CustomGPT能够设计自己的人…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统&#xff0c;它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间&#xff0c;使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的&#xff0c;要在 …...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...