Linux--线程--互斥锁

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);//创建线程t1if(ret == 0){printf("main:创建线程t1成功!\n");}ret = pthread_create(&t2,NULL,func2,(void *)&param);//创建线程t2if(ret == 0){printf("main:创建线程t2成功!\n");}ret = pthread_create(&t3,NULL,func3,(void *)&param);//创建线程t3if(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);//创建线程t1if(ret == 0){printf("main:创建线程t1成功!\n");}ret = pthread_create(&t2,NULL,func2,(void *)&param);//创建线程t2if(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.mzph.cn/news/127070.shtml

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

相关文章

基于深度学习的语音识别算法的设计与实现

收藏和点赞&#xff0c;您的关注是我创作的动力 文章目录 概要 一、课题内容二、需求分析2.1 算法需求分析2.2 语音录制2.3 声学模型2.4 语言模型2.5 训练集和测试集2.6 深度神经网络 三 算法设计原理3.1 语音识别系统3.1.1 声学模型3.1.2 语言模型3.1.3 发音词典 四 简单问答…

全新二开游戏支付通道/话费/电网、紫水晶带云端源码

源码修复可用&#xff0c;YY业务都可用 本店所售程序只供测试研究&#xff0c;不得使用于非法用途&#xff0c;不得违反国家法律&#xff0c;不得用于进行违法行为&#xff0c;否则后果自负&#xff01;购买以后用作他用附带的一切法律责任后果都由购买者承担于本店无任何关…

有效的数独

题目链接 有效的数独 题目描述 注意点 board.length 9board[i].length 9board[i][j] 是一位数字&#xff08;1-9&#xff09;或者 ‘.’ 解答思路 首先判断行是否满足数独条件&#xff0c;再判断列是否满足数独条件&#xff0c;最后再判断划分的3x3方格是否满足数独条件…

PCI9054入门1:硬件引脚定义、时序、FPGA端驱动源码

文章目录 1&#xff1a;PCI9054的FPGA侧&#xff08;local侧引脚定义&#xff09;2&#xff1a;PCI9054的C模式下的读写时序3&#xff1a;FPGA代码部分具体代码&#xff1a; 1&#xff1a;PCI9054的FPGA侧&#xff08;local侧引脚定义&#xff09; 而PCI9054的本地总线端的主要…

小程序day01

简介: 小程序项目的基本结构 页面的组成部分 一个页面对应一个文件夹&#xff0c;所有有关的内容都放在一起。 JSON配置文件 2.app.json文件 3.project.config.json文件 4.sitemap.json文件 5.页面的.json配置文件 6. 新建小程序页面 7.修改项目首页 小程序代码构成 小程序的宿…

zabbix6.4监控centos

1、关闭防火墙 setenforce 0 #关闭SELinux sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config #设置永久关闭SELinux systemctl stop firewalld.service #关闭防火墙 systemctl disable firewalld.service …

VScode clangd 插件浏览 linux 源码

文章目录 VScode clangd 插件浏览 linux 源码clangd 安装与配置VScode 插件安装clangd 安装方法一方法二 clangd 配置 cmake 生成bear 生成 compile_commands.json触发 clangd linux 内核脚本生成 compile_commands.json 文件三种方式对比 VScode clangd 插件浏览 linux 源码 …

【计算机网络笔记】传输层——可靠数据传输之流水线机制与滑动窗口协议

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

2023秋《论文写作》课程总结

2023秋《论文写作》课程总结 授课教师为闵帆教授&#xff0c;原文链接《论文写作》 文章目录 2023秋《论文写作》课程总结一、关于写作工具二、关于写作中的单词、短语、语法等三、关于论文题目四、关于摘要和关键词五、关于引言部分六、关于方法及实验部分七、关于结论八、关…

vue+element ui中的el-button自定义icon图标

实现 button的icon属性自定义一个图标名称&#xff0c;这个自定义的图标名称会默认添加到button下i标签的class上&#xff0c;我们只需要设置i标签的样式就可以了 ##3. 按钮上使用自定义的icon 完整代码 <div class"lookBtn"><el-button icon"el-icon-…

CSS与基本选择器

<div class"c1" id"d1"></div> CSS基本知识 什么是css&#xff1a;CSS&#xff08;Cascading Style Sheet&#xff0c;层叠样式表)定义如何显示HTML元素。 当浏览器读到一个样式表&#xff0c;他就会按照这个样式l来进行渲染。其实就是让HT…

ChatGPT火了:还有哪些可以做的变现项目

一、写在前面 柴特鸡皮踢 大家都不陌生了 说实话&#xff0c;Chatgpt火了后&#xff0c;正经的项目没出来多少&#xff0c;出了一大批割九菜的。 为什么说是割韭菜&#xff0c;因为一群完全不懂技术&#xff0c;只会讲讲成功学、写作学、财经的大V也敢开社群、卖课。很多人听…

Linux中正则表达式等

grep命令&#xff1a;主要作用就是过滤查找文本内容 常用的选项有&#xff1a; -m 数字:匹配几次之后停止&#xff0c;按行匹配&#xff0c;不是按字符个数&#xff0c;例如 -v:取反 例如: -n:显示匹配的行号 例如&#xff1a; -c:仅显示匹配的行数&#xff0c;不显示匹配内…

基于Docker-consul容器服务更新与发现

目录 一、什么是服务注册与发现&#xff1a; 二、Docker-consul介绍&#xff1a; 三、consul的关键特性&#xff1a; 四、consul部署&#xff1a; 1.部署规划&#xff1a; 2.consul服务器部署&#xff1a; 2.1 建立consul服务&#xff1a; 启动consul后默认会监听5个端口&a…

c++ 实现二叉搜索树

二叉搜索树的概念 二叉搜索树 (BST&#xff0c;Binary Search Tree)&#xff0c;也称二叉排序树或二叉查找树。它要么是一颗空树&#xff0c;要么是满足以下性质的二叉树&#xff1a; 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值。若它的右子树不为…

Ubuntu MySQL客户端功能介绍(mysql-client)mysql命令(mysql客户端命令)数据库导出、数据库导入

文章目录 Ubuntu MySQL客户端(mysql-client)功能介绍MySQL客户端与服务端服务器端&#xff08;MySQL Server&#xff09;客户端&#xff08;MySQL Client&#xff09; 安装MySQL客户端连接到MySQL服务器&#xff08;mysql -h host -u user -p&#xff09;执行SQL查询批处理模式…

Spring - 手写模拟Spring底层原理

手写Spring 定义配置类AppConfig ComponentScan("com.spring.zsj") public class AppConfig {Beanpublic ApplicationListener applicationListener() {return new ApplicationListener() {Overridepublic void onApplicationEvent(ApplicationEvent event) {System…

【案例】3D地球(vue+three.js)

需要下载插件 <template><div class"demo"><div id"container" ref"content"></div></div> </template> <script> import * as THREE from three; // import mapJSON from ../map.json; import { Or…

pytorch 笔记:KLDivLoss

1 介绍 对于具有相同形状的张量 ypred​ 和 ytrue&#xff08;ypred​ 是输入&#xff0c;ytrue​ 是目标&#xff09;&#xff0c;定义逐点KL散度为&#xff1a; 为了在计算时避免下溢问题&#xff0c;此KLDivLoss期望输入在对数空间中。如果log_targetTrue&#xff0c;则目标…

新一代构建工具Vite-xyphf

一、什么vite? vite:是一款思维比较前卫而且先进的构建工具,他解决了一些webpack解决不了的问题——在开发环境下可以实现按需编译&#xff0c;加快了开发速度。而在生产环境下&#xff0c;它使用Rollup进行打包&#xff0c;提供更好的tree-shaking、代码压缩和性能优化&…