Linux线程——互斥锁

概念

互斥量(mutex)从本质上来说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量进行加锁后,任何其他试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁

如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上的阻塞线程都会变成可运行状态,第一个变为可运行状态的线程可以对互斥量加锁,其他线程将会看到互斥锁依然被锁住,只能回去等待它重新变为可用。在这种方式下,每次只有一个线程可以向前运行

在设计时需要规定所有的线程必须遵守相同的数据访问规则。只有这样,互斥机制才能正常工作。操作系统并不会做数据访问的串行化。如果允许其中的某个线程在没有得到锁的情况下也可以访问共享资源,那么即使其它的线程在使用共享资源前都获取了锁,也还是会出现数据不一致的问题

互斥变量用pthread_mutex_t数据类型表示。在使用互斥变量前必须对它进行初始化,可以把它置为常量PTHREAD_MUTEX_INITIALIZER(只对静态分配的互斥量),也可以通过调用pthread_mutex_init函数进行初始化。如果动态地分配互斥量(例如通过调用malloc函数),那么在释放内存前需要调用pthread_mutex_destroy

常用API

包含的头文件

#include <pthread.h>

创建互斥锁

函数原型
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
参数解读
*mutex锁的地址,需定义一个pthread_mutex_t类型的全局变量。
attr互斥量的属性,一般设为NULL,要用默认的属性初始化互斥量,只需把attr设置为NULL。
返回值

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

销毁互斥锁

函数原型
int pthread_mutex_destroy(pthread_mutex_t mutex);
参数解读

*mutex:锁的地址,需定义一个pthread_mutex_t类型的全局变量。

返回值

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

加锁互斥锁

函数原型
int pthread_mutex_lock(pthread_mutex_t mutex);
参数解读

*mutex:锁的地址,需定义一个pthread_mutex_t类型的全局变量。

返回值

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

如果线程不希望被阻塞,它可以使用pthread_mutex_trylock尝试对互斥量进行加锁如果调用pthread_mutex_trylock时互斥量处于未锁住状态,那么pthread_mutex_trylock将锁住互斥量,不会出现阻塞并返回0,否则pthread_mutex_trylock就会失败,不能锁住互斥量,而返回EBUSY。

解锁互斥锁

函数原型
int pthread_mutex_unlock(pthread_mutex_t *mutex);
参数解读

*mutex:锁的地址,需定义一个pthread_mutex_t类型的全局变量。

返回值

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

代码示例

互斥锁的创建及加锁解锁

#include <stdio.h>
#include <pthread.h>int data = 0;pthread_mutex_t mutex;//定义一个互斥锁void *func1(void *arg)
{int i;pthread_mutex_lock(&mutex);//上锁 执行到该锁时会进行其中代码 直到解锁后才会进行其他代码for(i=0;i<5;i++){printf("t1:this thread t1:%ld \n",(unsigned long)pthread_self());printf("t1:num=%d\n",*((int *)arg));}pthread_mutex_unlock(&mutex);//解锁}void *func2(void *arg)
{pthread_mutex_lock(&mutex);printf("t2:this thread t2:%ld \n",(unsigned long)pthread_self());printf("t2:num=%d\n",*((int *)arg));pthread_mutex_unlock(&mutex);
}int main()
{int ret;int num =999;pthread_t t1;pthread_t t2;pthread_mutex_init(&mutex,NULL);//初始化互斥锁ret = pthread_create(&t1,NULL,func1,(void *)&num);if(ret == 0){printf("main:create thread success\n");}ret = pthread_create(&t2,NULL,func2,(void *)&num);if(ret == 0){printf("main:create thread success\n");}printf("main:%ld\n",(unsigned long)pthread_self());	pthread_join(t1,NULL);pthread_join(t2,NULL);	pthread_mutex_destroy(&mutex);//销毁互斥锁return 0;
}

 

由编译结果可知:t1会被main函数打断,但是不会被t2,t3打断,t1运行后t2,t3才能运行。

互斥锁限制共享资源的访问

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>int data = 0;pthread_mutex_t mutex;void *func1(void *arg)
{printf("t1:this thread t1:%ld \n",(unsigned long)pthread_self());printf("t1:num=%d\n",*((int *)arg));pthread_mutex_lock(&mutex); //上锁后执行下面语句while(1){printf("ti:%d\n",data++);sleep(1);if(data==3){pthread_mutex_unlock(&mutex);//解锁printf("over!!!!!!!!!!!!!!!!!!\n");//执行后结束func1线程//		pthread_exit(NULL);exit(0);//执行后结束整个进程}}
}void *func2(void *arg)
{printf("t2:this thread t2:%ld \n",(unsigned long)pthread_self());printf("t2:num=%d\n",*((int *)arg));while(1){printf("t2:%d\n",data);pthread_mutex_lock(&mutex);//func2进入检测锁的循环 判断func1是否解锁data++;pthread_mutex_unlock(&mutex);sleep(1);}
}int main()
{int ret;int num =999;pthread_t t1;pthread_t t2;pthread_mutex_init(&mutex,NULL);ret = pthread_create(&t1,NULL,func1,(void *)&num);if(ret == 0){printf("main:create thread success\n");}ret = pthread_create(&t2,NULL,func2,(void *)&num);if(ret == 0){printf("main:create thread success\n");}printf("main:%ld\n",(unsigned long)pthread_self());	while(1){printf("main:%d\n",data);sleep(1);}pthread_join(t1,NULL);pthread_join(t2,NULL);	pthread_mutex_destroy(&mutex);return 0;
}

由编译结果可知,func1线程结束后整个进程结束。

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

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

相关文章

【HCIP学习记录】OSPF之DD报文

1.OSPF报文格式 24字节 字段长度含义Version1字节版本&#xff0c;OSPF的版本号。对于OSPFv2来说&#xff0c;其值为2。Type1字节类型&#xff0c;OSPF报文的类型&#xff0c;有下面几种类型&#xff1a; 1&#xff1a;Hello报文&#xff1b;● 2&#xff1a;DD报文&#xff1…

美国联邦机动车安全标准-FMVSS

FMVSS标准介绍&#xff1a; FMVSS是美国《联邦机动车安全标准》&#xff0c;由美国运输部下属的国家公路交通安全管理局(简称NHTSA)具体负责制定并实施。是美国联邦政府针对机动车制定的安全标准&#xff0c;旨在提高机动车的安全性能&#xff0c;减少交通事故中的人员伤亡。F…

ubuntu无 root 权限安装 screen

网上的方法主要是如下图的方法&#xff0c;源码安装&#xff0c;但是我一直 make install失败显示没有权限 然后选择放弃&#xff0c;然后随便试了一下方法 2&#xff0c;成功 方法 1 方法 2 pip3 install screen结果&#xff1a;

生物识别应用指纹的算法是什么样的?有什么性能?

方案特点 • 采用金融级安全芯片 ACH512 的指纹模组&#xff0c;指纹和密码安全存储&#xff0c;云端数据安全传输 • 采用高性能指纹专用安全MCU芯片ACM32FP4&#xff0c;支持小点阵图像算法处理 • 支持80*64、88*112、96*96、160*160、192*192等像素传感器 • 已适配传…

Ubuntu系统使用Nginx搭建RTMP服务器

环境&#xff1a; 推流端 rockpi s 主控rk3308 运行ubuntu系统 服务端 ubuntu 播放器 VLC播放器 服务端安装依赖&#xff1a; apt-get install build-essential libpcre3 libpcre3-dev libssl-dev创建nginx编译目录&#xff1a; mkdir my_nginx_rtmp cd my_nginx_rtmp/下载 …

计算机网络:物理层(编码与调制)

今天又学会了一个知识&#xff0c;加油&#xff01; 目录 一、基带信号与宽带信号 1、基带信号 2、宽带信号 3、选择 4、关系 二、数字数据编码为数字信号 1、非归零编码【NRZ】 2、曼彻斯特编码 3、差分曼彻斯特编码 4、归零编码【RZ】 5、反向不归零编码【NRZI】 …

查找Apple Watch的序列号有重要意思,主要有两种方法

如果你打算购买二手Apple Watch&#xff0c;你可能需要检查它的序列号或IMEI号&#xff0c;来确保可靠性。以下是如何从Apple Watch和iPhone中查找序列号。 在Apple Watch上查找序列号和IMEI 1、在Apple Watch上&#xff0c;按下手表表面的数字皇冠以打开应用程序网格或列表。…

【设计模式--行为型--访问者模式】

设计模式--行为型--访问者模式 访问者模式定义结构案例优缺点使用场景扩展分派动态分派静态分派双分派 访问者模式 定义 封装一些作用于某种数据结构中的各元素的操作&#xff0c;它可以在不改变这个数据结构的前提下定义作用于这些元素的新操作。 结构 抽象访问者角色&…

晶体管的工作状态判断和工作条件

晶体管是模拟电路中基础的器件&#xff0c;对于电子工程师来说&#xff0c;了解晶体管工作的条件和判断晶体管的工作状态都是非常基础的&#xff0c;本文将带大家一起学习或回顾一下。 一、晶体管工作的条件 1.集电极电阻Rc&#xff1a; 在共发射极电压放大器中&#xff0c;…

HPM6750系列--第十篇 时钟系统

一、目的 上一篇中《HPM6750系列--第九篇 GPIO详解&#xff08;基本操作&#xff09;》我们讲解了HPM6750 GPIO相关内容&#xff0c;在进一步讲解其他外设功能之前我们有必要先讲解一下HPM6750的时钟系统。 时钟可以说是微控制器系统中的心脏&#xff0c;片上外设模块必须依赖时…

爱普生手机打印助手Epson Smart Panel下载分享

新一代智能打印Epson Smart Panel为您提供一站式打印服务&#xff0c;人性化装机助手&#xff0c;智能联网&#xff0c;快速开启远程微信打印&#xff0c;全新交互式设计&#xff0c;打印体验焕新升级&#xff1b; 根据手机不同可选下列不同下载方式&#xff1a; 人性化智能装机…

《每天一分钟学习C语言·一》

1、转义字符&#xff1a;\n换行&#xff0c;\t前进一个tab键&#xff0c;\b退格键 2、八进制前面有0&#xff0c;%o或者%#o表示八进制&#xff0c;十六进制前有0X&#xff0c;%0x或者%#0x表示十六进制 3、%u打印无符号数&#xff0c;%g显示小数&#xff0c;类似于%f&#xff…

LibreNMS:从docker出发

引言 LibreNMS 是一个免费开源的网络监控和自动化工具&#xff0c;用于监视网络设备、服务器和应用程序的性能和状态。它提供了一个集中的管理平台&#xff0c;帮助管理员实时监控和管理整个网络基础设施。 以下是 LibreNMS 的一些主要特点和功能&#xff1a; 自动发现&#…

TikTok矩阵玩法分享,如何建立TikTok矩阵?

矩阵是在 TikTok 上非常常见的营销方式&#xff0c;很多卖家想要通过矩阵化运营快速涨粉。但要想做好TikTok矩阵&#xff0c;需要有明确的方向和计划。下面东哥我将分享一些做TikTok矩阵的玩法&#xff0c;帮助大家更好地搭建自己的TikTok矩阵。 了解TikTok矩阵 TikTok矩阵是一…

同时获取el-select的label和value

ui如下&#xff1a; 需求如下&#xff1a; 在点击确认的时候&#xff0c;将id和name都传给一个接口&#xff0c;但是ui只用展示name&#xff0c;name用v-model绑定给input框&#xff0c;但是id不知道怎么传给后端。 解决方法如下&#xff1a; vue中elementUi的el-select同时…

JVM-9-Class类文件的结构

Java技术能够一直保持着非常良好的向后兼容性&#xff0c;Class文件结构的稳定功不可没。 Class文件是一组以8个字节为基础单位的二进制流&#xff0c;各个数据项目严格按照顺序紧凑地排列在文件之中。 Class文件格式采用一种类似于C语言结构体的伪结构来存储数据&#xff0c…

c语言突击

一&#xff1a;前序 1.一个c语言程序有且只有一个main函数&#xff0c;是程序运行的起点&#xff01; 每个c语言程序写完后&#xff0c;都是先编译&#xff08;.c---&#xff09;&#xff0c;后链接&#xff08;.obj---&#xff09;&#xff0c;最后运行&#xff08;.exe&…

JAVA的三大版本

&#x1f34e;个人主页 &#x1f3c6;​​​​​​​个人专栏&#xff1a;日常聊聊 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 一、Java 二、JavaSE&#xff08;Java Standard Edition&#xff09; 三、JavaME&#xff08;Java Micro Edition&#xff09; 四、JavaE…

文件操作(下)

标题的顺序是接着之前写的&#xff0c;希望这篇博客对你有帮助 七. 随机读写函数 实际上&#xff0c;无论是读还是写&#xff0c;在一次调用顺序读写函数&#xff0c;文件指针会移到已经读过或者写过的下一个位置&#xff0c;从那个位置开始下一次读和写&#xff08;在文件没有…

制作RK3568 ubuntu20.04桌面版镜像

平台 主控: RK3568 编译主机: Ubuntu 20.04 AMD64 目标版本: Ubuntu 20.04 概述 RK3568是极具性价比的高能国产“芯“ , 是Rockchip面向与AIOT和工业市场打造的一款高性能、低功耗、功能丰富的国产化应用处理器。采用四核64位Cortex-A55架构&#xff0c;主频高达2.0GHz&#x…