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.hqwc.cn/news/156935.html

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

相关文章

Javassist讲解1(介绍,读写字节码)

Javassist讲解1&#xff08;介绍&#xff0c;读写字节码&#xff09; 介绍一、读写字节码1.如何创建新的类2.类冻结 介绍 javassist 使Java字节码操作变得简单&#xff0c;它是一个用于在Java中编辑字节码的类库&#xff1b; 它使Java程序能够在运行时定义一个新类&#xff0c;…

okhttp post请求 header post参数加密遇到的两个问题

如果你对于网络请求用了https后是否还有必要对参数加密有疑问可以看我上篇的文章&#xff1a;网络安全https 记得耐心看完&#xff0c;下面说问题&#xff1a; Caused by: java.lang.IllegalArgumentException: Unexpected char 0x0a 一开始以为是okhttp框架对特殊字符做了现在…

【面试经典150 | 链表】旋转链表

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;遍历 其他语言python3 写在最后 Tag 【单向链表】 题目来源 61. 旋转链表 题目解读 旋转链表&#xff0c;将链表的每个节点向右移动 k 个位置。 解题思路 方法一&#xff1a;遍历 本题题目意思清晰&#xff0c;实现…

掌握 JavaScript 的基本语法

一、javascript书写位置 JavaScript 可以写在 HTML 页面中的以下三个位置&#xff1a; 内联脚本&#xff1a;将 JavaScript 代码直接写在 HTML 元素的 onclick、onload、onsubmit 等事件属性中。例如&#xff1a; <button onclick"alert(Hello World)">点击我…

【计算机网络】计算机网络中的基本概念

文章目录 局域网LAN基于网线直连基于集线器组建基于交换机组建基于交换机和路由器组建 广域网WANIP地址端口号协议为什么要有协议知名协议的默认端口 五元组协议分层TCP/IP五层模型封装和分用 网络互连就是将多台计算机连接在一起&#xff0c;完成数据共享。数据共享本质是网络…

【易售小程序项目】后端部署、Uniapp项目Web部署

文章目录 Uniapp项目Web打包部署为什么不部署小程序Web打包前对项目进行调整网站、小程序切换增加constant.js来控制常量将js绑定到main.js的全局变量中 WebSocket差异监听键盘呼出导航条打包部署 后端项目打包部署打包前准备打包部署 Uniapp项目Web打包部署 为什么不部署小程…

通过内网穿透快速搭建公网可访问的Spring Boot接口调试环境

文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…

idea 配置checkstyle全过程

checkstyle是提高代码质量,检查代码规范的很好用的一款工具&#xff0c;本文简单介绍一下集成的步骤&#xff0c;并提供一份完整的checkstyle的代码规范格式文件&#xff0c;以及常见的格式问题的解决方法。 一&#xff0c;安装 打开idea的文件选项&#xff0c;选择设置&…

恒驰服务 | 华为云数据使能专家服务offering之大数据建设

恒驰大数据服务主要针对客户在进行智能数据迁移的过程中&#xff0c;存在业务停机、数据丢失、迁移周期紧张、运维成本高等问题&#xff0c;通过为客户提供迁移调研、方案设计、迁移实施、迁移验收等服务内容&#xff0c;支撑客户实现快速稳定上云&#xff0c;有效降低时间成本…

wireshark捕获DNS

DNS解析&#xff1a; 过滤项输入dns&#xff1a; dns查询报文 应答报文&#xff1a; 事务id相同&#xff0c;flag里 QR字段1&#xff0c;表示响应&#xff0c;answers rrs变成了2. 并且响应报文多了Answers 再具体一点&#xff0c;得到解析出的ip地址&#xff08;最底下的add…

react-markdown支持83版本的Chrome,解决Object.hasOwn is not a function问题

旧版浏览器支持 react-markdown用了一个ES2022的api&#xff0c;Object.hasOwn测试的时候一切正常&#xff0c;当我切换到生成环境的旧版的83的Chrome之后&#xff0c;发现会报Object.hasOwn is not a function这个错误。 https://github.com/remarkjs/react-markdown/issues/…

21.12 Python 实现网站服务器

Web服务器本质上是一个提供Web服务的应用程序&#xff0c;运行在服务器上&#xff0c;用于处理HTTP请求和响应。它接收来自客户端&#xff08;通常是浏览器&#xff09;的HTTP请求&#xff0c;根据请求的URL、参数等信息生成HTTP响应&#xff0c;并将响应返回给客户端&#xff…