互斥锁概述

1. 同步互斥概述

在多任务操作系统中,同时运行的多个任务可能都需要访问/使用同一种资源多个任务之间有依赖关系,某个任务的运行依赖于另一个任务同步和互斥就是用于解决这两个问题的。

互斥:一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源。POSIX标准中进程和线程同步和互斥的方法,主要有信号量和互斥锁两种方式。

同步:两个或两个以上的进程或线程在运行过程中协同步调,按预定的先后次序运行。

同步就是在互斥的基础上有顺序。

2. 互斥锁

mutex是一种简单的加锁的方法来控制对共享资源的访问,mutex只有两种状态,即上锁(lock)和解锁(unlock)。在访问该资源前,首先应申请mutex,如果mutex处于unlock状态,则会申请到 mutex并立即lock;如果mutex处于lock状态,则默认阻塞申请者。unlock操作应该由lock者进行

2.1 创建互斥锁

mutex用pthread_mutex_t 数据类型表示,在使用互斥锁前,必须先对它进行初始化。

2.2 静态分配的互斥锁:

pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;

2.3 动态分配互斥锁:

pthread_mutex_t  mutex;

pthread_mutex_init(&mutex, NULL);在所有使用过此互斥锁的线程都不再需要使用时候,应调用销毁互斥锁;

2.4 销毁互斥锁

pthread_mutex_destroy

3. 初始化互斥锁(pthread_mutex_init)

需要包含的头文件:

#include <pthread.h>

函数结构:int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr);

功能:初始化一个互斥锁

参数:

  1. mutex:指定的互斥锁

  2. mutexattr:互斥锁的属性,为NULL表示默认属性

返回值:

  1. 成功:0

  2. 失败:非0

4. 互斥锁上锁(pthread_mutex_lock)

需要包含的头文件:

#include <pthread.h>

int pthread_mutex_lock(pthread_mutex_t* mutex);

功能:对互斥锁上锁,若已经上锁,则调用者一直阻塞到互斥锁解锁

参数:

  1. mutex:指定的互斥锁

返回值:

  1. 成功:0
  2. 失败:非0
 4.1 非阻塞(pthread_mutex_trylock)

需要包含的头文件:

#include <pthread.h>

int pthread_mutex_trylock(pthread_mutex_t* mutex);

功能:对互斥锁上锁,若已经上锁,则上锁失败,函数立即返回

参数:

  1. mutex:互斥锁地址。

返回值:

  1. 成功:0
  2. 失败:非0

 5. 互斥锁解锁(pthread_mutex_unlock)

需要包含的头文件:

#include <pthread.h>

函数结构:int pthread_mutex_unlock(pthread_mutex_t * mutex);

功能:对指定的互斥锁解锁。

参数:

  1. mutex:互斥锁地址。

返回值:

  1. 成功:0
  2. 失败:非0

6. 互斥锁销毁(pthread_mutex_destroy)

需要包含的头文件:

#include <pthread.h>

函数结构:int pthread_mutex_destroy(pthread_mutex_t * mutex);

功能:销毁指定一个互斥锁。

参数:

  1. mutex:互斥锁地址。

返回值:

  1. 成功:0
  2. 失败:非0

7. 不使用互斥锁

代码演示: 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>int money = 10000;void *pthread_fun1(void *arg)
{int get, yu, shiji;get = 10000;printf("张三正在查询余额...\n");sleep(1);yu = money;printf("张三正在取钱...\n");sleep(1);if(get > yu){shiji = 0;}else {shiji = get;yu = yu - get;money = yu;}printf("张三想取%d元,实际取了%d元,余额为%d元\n", get, shiji, yu);pthread_exit(NULL);
}void *pthread_fun2(void *arg)
{int get, yu, shiji;get = 10000;printf("李四正在查询余额...\n");sleep(1);yu = money;printf("李四正在取钱...\n");sleep(1);if(get > yu){shiji = 0;}else {shiji = get;yu = yu - get;money = yu;}printf("李四想取%d元,实际取了%d元,余额为%d元\n", get, shiji, yu);pthread_exit(NULL);
}int main(int argc, char const *argv[])
{pthread_t thread1, thread2;if(pthread_create(&thread1, NULL, pthread_fun1, NULL) != 0){perror("fail to pthread_create");exit(1);}if(pthread_create(&thread2, NULL, pthread_fun2, NULL) != 0){perror("fail to pthread_create");exit(1);}pthread_join(thread1, NULL);pthread_join(thread2, NULL);return 0;
}

 执行结果:

8. 使用互斥锁

代码演示: 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>//通过互斥锁解决线程间互斥问题int money = 10000;//第一步:创建互斥锁(由于两个线程操作同一个互斥锁,所以定义在全局更加方便一点)
pthread_mutex_t mymutex;void *pthread_fun1(void *arg)
{int get, yu, shiji;get = 10000;//第三步:对共享资源的操作进行上锁pthread_mutex_lock(&mymutex);printf("张三正在查询余额...\n");sleep(1);yu = money;printf("张三正在取钱...\n");sleep(1);if(get > yu){shiji = 0;}else {shiji = get;yu = yu - get;money = yu;}printf("张三想取%d元,实际取了%d元,余额为%d元\n", get, shiji, yu);//第四步:当共享资源的操作执行完毕后,对互斥锁执行解锁操作pthread_mutex_unlock(&mymutex);pthread_exit(NULL);
}void *pthread_fun2(void *arg)
{int get, yu, shiji;get = 10000;//第三步:对共享资源的操作进行上锁pthread_mutex_lock(&mymutex);printf("李四正在查询余额...\n");sleep(1);yu = money;printf("李四正在取钱...\n");sleep(1);if(get > yu){shiji = 0;}else {shiji = get;yu = yu - get;money = yu;}printf("李四想取%d元,实际取了%d元,余额为%d元\n", get, shiji, yu);//第四步:当共享资源的操作执行完毕后,对互斥锁执行解锁操作pthread_mutex_unlock(&mymutex);pthread_exit(NULL);
}int main(int argc, char const *argv[])
{//第二步:初始化互斥锁pthread_mutex_init(&mymutex, NULL);pthread_t thread1, thread2;if(pthread_create(&thread1, NULL, pthread_fun1, NULL) != 0){perror("fail to pthread_create");exit(1);}if(pthread_create(&thread2, NULL, pthread_fun2, NULL) != 0){perror("fail to pthread_create");exit(1);}pthread_join(thread1, NULL);pthread_join(thread2, NULL);//第五步:当互斥锁使用完毕后,要销毁pthread_mutex_destroy(&mymutex);return 0;
}

执行结果:

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

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

相关文章

谷粒商城实战(023 业务-订单模块-页面和幂等性等校验)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第270p-第p283的内容 简介 远程调用的服务已经注册到了注册中心 校验 幂等性校验 拿令牌 读令牌 删令牌 要实现 原子性 在一个事务中 添加令牌…

使用注解的方式进行配置RabbitMQ

引入依赖&#xff1a; <dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit-test</artifactId><scope>test</scope></dependency> 配置application.yml server:port: 8082 spring:rabbitmq…

堆排序 之实现最小的K个数

目录 1、方式一&#xff1a;通过自定义实现建堆和堆化操作 2、方式二&#xff1a;借助模块heapq实现 2.1、模块heapq的基本使用 2.2、使用heapq实现最小的k个数 3、堆在实际项目的应用 实现语言&#xff1a;Python 3.9 题目来源&#xff1a;牛客 分析&#xff1a; 要找…

Tiff文件解析和PackBits解压缩

实现了Tiff图片文件格式的解析&#xff0c;对Tiff文件中的PackBits压缩格式进行解压缩&#xff0c;对Tiff文件中每一个Frame转换成BufferedImage显示。 Java语言实现&#xff0c;Eclipse下开发&#xff0c;AWT显示图片。 public static TIFF Parse(final byte[] bytes) throw…

es6语法总结

【1】语法 &#xff08;1&#xff09;声明变量(let-var-const) 变量提升&#xff1a; 是JavaScript引擎在代码执行前将变量的声明部分提升到作用域顶部的行为。尽管变量的声明被提升了&#xff0c;变量的赋值&#xff08;即初始化&#xff09;仍然保留在原来的位置。因此&…

原型模式类图与代码

现要求实现一个能够自动生成求职简历的程序&#xff0c;简历的基本内容包括求职者的姓名、性别、年龄及工作经历。希望每份简历中的工作经历有所不同&#xff0c;并尽量减少程序中的重复代码。 采用原型模式(Prototype)来实现上述要求&#xff0c;得到如图 7.25 所示的类图。 原…

达梦数据库连接失败:Connect Failure! “Encryption module failed to load“

初次安装达梦数据库&#xff1a;V7 QT5.12.12版本开发调用数据库&#xff0c;最基础的原型调用&#xff1a; { //执行查询语句或则执行sql语句 QSqlDatabase qDb; QSqlDatabase db QSqlDatabase::addDatabase("QDM"); db.setHostName("192.168.2…

PX4 路径规划 航点规划 轨迹跟踪 Matlab/Simulink

一、无人机轨迹算法和仿真 matlab下载和安装 PX4实战之旅_超维空间科技的博客-CSDN博客 查了很多资料。无人机二次开发设计的目标是实现喷涂路径程序设计。决定使用simulink在ubuntu系统上结合jmavsim进行算法设计和仿真。 1.如果安装在ubuntu系统上面&#xff0c;MATLAB占…

基于单片机的直流电机检测与控制系统

摘要&#xff1a; 文章设计一款流电机控制系统&#xff0c;以 STC89C51 作为直流电机控制系统的主控制器&#xff0c;采用 LM293 做为驱动器实现 对直流电机的驱动&#xff0c;采用霍尔实现对直流电机速度的检测&#xff1b;本文对直流电机控制系统功能分析&#xff0c;选择确…

工业中常见大数据技术组件

随着大数据技术在各行各业的广泛应用&#xff0c;数据产品经理的角色也变得越来越重要。了解常见的大数据技术组件对于数据产品经理来说至关重要&#xff0c;因为这有助于他们更好地设计产品架构和功能模块&#xff0c;满足数据处理和分析的需求。在处理海量数据的产品中&#…

计算机视觉——OpenCV实现Lucas-Kanade 光流追踪

1.光流 光流法是计算机视觉中用于估计图像序列中物体运动的关键技术。它类似于观察夜空中的彗星&#xff0c;通过其在天空中的运动轨迹来追踪它的路径。在图像处理中&#xff0c;光流帮助我们理解像素点如何在连续的帧之间移动。 1.1 稀疏光流法 稀疏光流法关注于图像中的关…

OpenCV 入门(二)—— 车牌定位

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…