Linux--线程--互斥锁

news2024/12/23 3:29:34

1.互斥量
a)互斥量(mutex)从本质上来说是一把锁,一般在主线程中定义一个互斥量,就是定义一把锁。然后根据我们的需求来对线程操作这把锁。

b)如果给所有的线程都加上锁了,线程们会去争取内存空间,谁先争取到谁先运行,直到该线程解锁后,期间其他线程只能等待阻塞。

c)因为主线程不上锁,在先拿到锁的线程在跑的过程中,主线程也会跟着跑。
 

include <pthread.h>
// 返回:若成功返回0,否则返回错误编号
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);创建锁
int pthread_mutex_lock(pthread_mutex_t *mutex);//加锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);//销毁锁
 

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

  要用默认的属性初始化互斥量,只需要把attr设置为NULL。
   

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

2.加锁解锁简单操作:

代码:

#include<stdio.h>
#include<pthread.h>
#include <unistd.h>

int data = 0;//定义一个全局变量data 
pthread_mutex_t mutex;//创建一把锁 
void *func1(void *arg)
{
        int i;
        pthread_mutex_lock(&mutex);//加锁

        for(i=0;i<5;i++){
                printf("t1:thread id is:%ld\n",(unsigned long)pthread_self());
                printf("t1:is param:%d\n",*((int *)arg));
                sleep(1);
        }

        pthread_mutex_unlock(&mutex);//解锁
}
void *func2(void *arg)
{
        pthread_mutex_lock(&mutex);//加锁

        printf("t2:thread id is:%ld\n",(unsigned long)pthread_self());
        printf("t2:is param:%d\n",*((int *)arg));

        pthread_mutex_unlock(&mutex);//解锁

}
void *func3(void *arg)
{
        pthread_mutex_lock(&mutex);//加锁

        printf("t3:thread id is:%ld\n",(unsigned long)pthread_self());
        printf("t3:is param:%d\n",*((int *)arg));

        pthread_mutex_unlock(&mutex);//解锁

}
int main()
{
        int ret;
        int param = 100;
        pthread_t t1;
        pthread_t t2;
        pthread_t t3;

        pthread_mutex_init(&mutex,NULL);//初始化锁

        ret = pthread_create(&t1,NULL,func1,(void *)&param);//创建线程t1
        if(ret == 0){
                printf("main:创建线程t1成功!\n");
        }

        ret = pthread_create(&t2,NULL,func2,(void *)&param);//创建线程t2
        if(ret == 0){
                printf("main:创建线程t2成功!\n");
        }

        ret = pthread_create(&t3,NULL,func3,(void *)&param);//创建线程t3
        if(ret == 0){
                printf("main:创建线程t3成功!\n");
        }
        printf("main:获取主程序的ID:%ld\n",(unsigned long)pthread_self());


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

        return 0;
}

结果:

先拿到锁的是t1线程先运行,但是会和主线程争抢内存,因为主线程没加锁,虽然会被打断,但是对于其他t2,t3线程,他们只有等待阻塞,等t1先运行完

3.互斥锁限制共享内存的访问

#include<stdio.h>
#include<pthread.h>
#include <unistd.h>
#include<stdlib.h>
int data = 0;//定义一个全局变量data 
pthread_mutex_t mutex;

void *func1(void *arg)
{

        pthread_mutex_lock(&mutex);
        while(1){
                printf("线程t1拿到 data = %d\n",data++);
                sleep(1);
                if(data == 5){
                   printf("t1:data = %d\n",data);
                   pthread_mutex_unlock(&mutex);
                   printf("=========t1线程退出============\n");
                   exit(0);
                }
        }

}
void *func2(void *arg)
{

        while(1){
                printf("线程t2拿到 data = %d\n",data);
                pthread_mutex_lock(&mutex);
                data++;
                pthread_mutex_unlock(&mutex);
                sleep(1);
        }
}
int main()
{
        int ret;
        int param = 100;
        pthread_t t1;
        pthread_t t2;

        pthread_mutex_init(&mutex,NULL);
        ret = pthread_create(&t1,NULL,func1,(void *)&param);//创建线程t1
        if(ret == 0){
                printf("main:创建线程t1成功!\n");
        }

        ret = pthread_create(&t2,NULL,func2,(void *)&param);//创建线程t2
        if(ret == 0){
                printf("main:创建线程t2成功!\n");
        }


        printf("主线程main拿到data:%d\n",data);
        pthread_join(t1,NULL);
        pthread_join(t2,NULL);

        pthread_mutex_destroy(&mutex);
        
        return 0;
}

结果:

t2解锁后,t1一直拿锁,知道循环结束,整个程序退出,因为是共享内存。

4.死锁

前提条件是定义了两把锁,其中一个线程拿到了第一把锁和第二把锁,另外的一个线程拿到了第二把锁和第一把锁,然后他们都在争用锁的使用权,因为都解他们各自拥有的第一把所,所以一直卡在争用锁锁的使用权。

代码:

#include <stdio.h>
#include <pthread.h>
 
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
pthread_mutex_t mutex;
pthread_mutex_t mutex2;
 
int g_data=0;
 
void *func1(void *arg)
{
	int i;
	pthread_mutex_lock(&mutex);
	sleep(1);
	pthread_mutex_lock(&mutex2);
 
	for(i=0;i<5;i++){
	printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
	printf("t1:param is %d\n",*((int*)arg));
	sleep(1);
	}
 
	pthread_mutex_unlock(&mutex);
}
void *func2(void *arg)
{
        pthread_mutex_lock(&mutex2);
	sleep(1);
        pthread_mutex_lock(&mutex);
 
        printf("t2:%ld thread is create\n",(unsigned long)pthread_self());
        printf("t2:param is %d\n",*((int*)arg));
 
        pthread_mutex_unlock(&mutex);
 
}
 
 
int main()
{
	int ret;
	int param=100;
	pthread_t t1;
	pthread_t t2;
	
	pthread_mutex_init(&mutex,NULL);
	pthread_mutex_init(&mutex2,NULL);
 
	ret=pthread_create(&t1,NULL,func1,(void*)&param);	
	if(ret==0){
		printf("main:create t1 success\n");
	}
        ret=pthread_create(&t2,NULL,func2,(void*)&param);
        if(ret==0){
                printf("main:create t2 success\n");
        }
 
	
	printf("main %ld \n",(unsigned long)pthread_self());
 
	pthread_join(t1,NULL);
	pthread_join(t2,NULL);
 
	pthread_mutex_destroy(&mutex);
	pthread_mutex_destroy(&mutex2);
 
	return 0;
}

结果:

main:create t1 success
main:create t2 success
main 139666438145792 
^C
CLC@Embed_Learn:~/thread$ ./a.out
main:create t1 success
main:create t2 success
main 139839917381376 
^C
CLC@Embed_Learn:~/thread$ ./a.out
main:create t1 success
main:create t2 success
main 139912974800640 
^C
CLC@Embed_Learn:~/thread$ 

只有1把锁的情况下是不会造成死锁的

在这里func1拿着锁mutex,需要拿锁mutex2;func2拿着锁mutex2,需要拿锁mutex;从而造成了死锁。

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

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

相关文章

2018年第三届 美亚杯电子取证 个人赛题解

1 Victor的笔记本电脑己成功取证并制作成法证映像档 (Forensic Image)&#xff0c;下列哪个是其MD5哈希值? (2分) A. FC20782C21751AB76B2A93F3A17922D0 B. 5F1BDEB87EE9F710C90CFB3A0BB01616 C. A0BB016160CFB3A0BB0161661670CFB3 D. 917ED59083C8B35C54D3FCBFE4C4BB0B E. F…

当你在浏览器地址栏输入一个URL后,将会发生的事情?个人笔记

客户端 在浏览器输入 URL 回车之后发生了什么&#xff08;超详细版&#xff09; - 知乎 (zhihu.com) 大致流程是&#xff1a; URL 解析DNS 查询TCP 连接处理请求接受响应渲染页面 1.URL解析 地址解析&#xff1a; 首先判断你输入是否是一个合法的URL还是一个待搜索的关键…

上市公司-供应链效率数据集(2000-2022年)

参照张倩肖&#xff08;2023&#xff09;、Feng&#xff08;2015&#xff09;、张树山&#xff08;2023&#xff09;的做法&#xff0c;团队以库存周转天数来衡量供应链效率 库存周转天数有效克服了因企业保留安全库存而导致供应链效率较低的测算误差&#xff0c;体现供应链上…

回归预测 | Matlab实现POA-CNN-SVM鹈鹕算法优化卷积神经网络-支持向量机多变量回归预测

Matlab实现POA-CNN-SVM鹈鹕算法优化卷积神经网络-支持向量机多变量回归预测 目录 Matlab实现POA-CNN-SVM鹈鹕算法优化卷积神经网络-支持向量机多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.POS-CNN-SVM鹈鹕算法优化卷积神经网络-支持向量机的多变量回归…

好用的CRM软件都有哪些功能?

好用的CRM软件不仅仅是将客户资料存档&#xff0c;更大的作用还在于充分发挥数据的价值提升客户管理效率。如果您了解过多款CRM软件就一定会发现它们的功能都不尽相同&#xff0c;但是好用的CRM工具离不开这些功能&#xff1a; 一、客户视图 客户视图主要由4类数据组成&#…

基于springboot实现游戏分享网站系统项目【项目源码+论文说明】

基于springboot实现游戏分享网站演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把游戏分享管理与现在网络相结合&#xff0c;利用java技术建设游戏分享网站&#xff0c;实现游戏分享的信息化。则对于进一步提高游戏分享管理发展&#xff0c;丰富游戏分享管理经验能起到…

跨境商城源码价格

在当今数字商务的时代&#xff0c;跨境电商已经成为了越来越多企业的选择。然而&#xff0c;要建立一个高效、便捷、全球化的跨境商城并不是一件简单的事情。所幸&#xff0c;现在有一个开源的解决方案&#xff0c;给企业提供了无限的可能性。跨境商城源码价格合乎实际&#xf…

浅谈AcrelEMS-CB商业建筑能源管理系统解决方案-安科瑞 蒋静

1概述 AcrelEMS-CB商业建筑能源管理系统&#xff0c;集电力监控、电能质量监测与治理、电气安全预警、能耗分析、照明控制、新能源使用、能源收费以及设备运维等功能于一体&#xff0c;通过一套系统对商业建筑的能源进行统一监控、统一运维和调度&#xff0c;系统可以通过WEB和…

对比学习(contrastive Learning)

起源和定义 自监督学习又可以分为对比学习(contrastive learning)和生成学习(generative learning)两条主要的技术路线。 比学习的核心思想是将正样本和负样本在特征空间对比&#xff0c;从而学习样本的特征表示&#xff0c;使得样本与正样本的特征表示尽可能接近。正样本和负…

webase编译合约一直转圈卡住解决方案

问题:webase编译合约一直转圈卡住,等再久也没反应 解决方案: 进入webase-web目录,然后进入static\js目录,执行以下命令: curl -#L https://osp-1257653870.cos.ap-guangzhou.myqcloud.com/WeBASE/download/solidity/wasm/v0.4.25.js -o v0.4.25.js curl -#L https://os…

Unity AssetBundle打包

1&#xff0c;AssetBundle的概念与作用 AssetBundle是一个存档文件&#xff0c;是Unity提供的一种用于存储资源的资源压缩包&#xff0c;可以包含模型、贴图、音频、预制体等。 Unity中的AssetBundle系统是对资源管理的一种扩展&#xff0c;通过将资源分布在不同的AB包中可以最…

SpringBoot--Web开发篇:含enjoy模板引擎整合,SpringBoot整合springMVC;及上传文件至七牛云;restFul

SpringBoot的Web开发 官网学习&#xff1a; 进入spring官网 --> projects --> SpringBoot --> LEARN --> Reference Doc. --> Web --> 就能看到上述页面 静态资源映射规则 官方文档 总结&#xff1a; 只要是静态资源&#xff0c;放在类路径下&#xff1…

制作网页版H5页面商城源码系统+随心DIY 带前后端完整搭建教程

随着智能手机的广泛普及&#xff0c;人们越来越依赖手机进行日常生活中的各种活动&#xff0c;包括购物。传统的PC端购物模式已经无法满足人们的需求&#xff0c;因此开发移动端的购物系统势在必行。而现如今H5技术不断发展成熟&#xff0c;使得在手机等移动设备上展示网页版商…

Nginx常见问题解决

一、修改nginx.conf报错 背景&#xff1a;修改nginx.conf&#xff0c;配置转发到tcp的信息&#xff1a; 在stream块中配置转发规则&#xff1a;在stream块中&#xff0c;使用server指令来配置转发规则。例如&#xff0c;如果你要将TCP流量转发到example.com:1234&#xff0c;可…

短视频矩阵营销系统工具如何助力商家企业获客?

1.批量剪辑技术研发 做的数学建模算法&#xff0c;数学阶乘的组合乘组形式&#xff0c;采用两套查重机制&#xff0c;一套针对素材进行查重抽帧素材&#xff0c;一套针对成片进行抽帧素材打分制度查重&#xff0c;自动滤重计入打分。 2.账号矩阵分发开发 多平台&#xff0c;…

[学习笔记]python绘制图中图(绘制站点分布图)

背景 在绘制站点分布图时&#xff0c;有时需要采用图中图的方式&#xff0c;以便于在一张图中尽可能多的表达信息。此处记录一下利用python matplotlib绘制图中图的脚本&#xff0c;方便然后查询。 包含数据 该绘图脚本中包含以下数据&#xff1a; CMONOC站点分布&#xff…

日本移动支付Merpay QA团队的自动化现状

Merpay是日本最大的网购平台之一Mercari的无现金支付系统。Merpay 的主要功能是让用户在 Mercari的网站上购物&#xff0c;也可以在日本的许多实体店和餐厅使用它&#xff0c;也可以理解为日本的“支付宝”。以下为Merpay QA 团队在自动化方面的一些思考&#xff1a; 这几年&am…

C++构建与编译

C构建 一般来讲&#xff0c;写完c的源文件&#xff08;src&#xff09;&#xff0c;就需要去编译为&#xff1a; 可执行文件动态库/静态库 那么就遇到了几个问题&#xff1a; 编译的主机是什么代码运行的目标平台是什么 主机 一般来讲工作的机器&#xff0c;Windows或者L…

vMix导播软件使用NDI协议输入输出

前两篇文章一直写NDI&#xff0c;写了NDI在OBS【链接】、芯象【链接】中的使用。有的朋友问在vMix中的用法&#xff0c;今天就详细说说。 vMix在软件导播领域可算大名鼎鼎&#xff0c;功能丰富、工作稳定&#xff0c;支持多种媒体导入。由它衍生出多种产品&#xff0c;如&#…

中考倒计时7个月复习攻略:名师支招,为“长跑”积蓄能量

今天是2023年11月2日&#xff0c;距离2024年中考还有7个月多一点的时间。其实据六分成长了解&#xff0c;很多学校到了初三&#xff08;九年级&#xff09;基本上都是奔着中考考试复习的&#xff0c;这一学年基本上是长跑、拉力赛&#xff0c;拼的不只是智力&#xff0c;还有体…