当前位置: 首页 > news >正文

[Linux]互斥锁(什么是锁,为什么需要锁,怎么使用锁(接口),演示代码)

目录

 

一、锁的概念

一些需要了解的概念

什么是锁?为什么需要锁?什么时候使用锁?怎么定义锁?

二、锁的接口

1.初始化锁

2.加锁

3.申请锁

4.解锁

5.销毁锁

三、实践(写代码):黄牛抢票

Makefile

test.cc

结果


 

一、锁的概念

一些需要了解的概念

  • 临界资源:任一时刻只允许一个线程访问的共享资源
  • 临界区:访问临界资源的代码
  • 原子性:不会被任何调度机制打断的操作,该操作只有两态:要么完成,要么未完成
  • 互斥:任何时刻,互斥可以保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用,而锁就是实现互斥的。
  • 同步:同步是一种机制,用于协调不同进程、线程或设备之间的操作,确保它们按照预期的顺序和方式进行。同步的目的是保持数据的一致性和系统的稳定性。

什么是锁?为什么需要锁?什么时候使用锁?怎么定义锁?

什么是锁?

锁是一种同步机制,用于控制多个线程对共享资源的访问。通过锁,可以确保一次只有一个线程能够访问特定的代码段或数据,从而防止数据竞争和不一致。锁的主要目的是确保数据的一致性和线程安全性。

为什么需要锁?

需要锁的主要原因在于确保多线程或多用户环境中共享资源访问的原子性和数据一致性。在多线程应用中,若多个线程同时访问并修改同一资源,可能导致数据冲突、不一致甚至损坏。

故事说明:把线程比作一个学生,小明,锁是自习室的门口上的锁头,当小明要进自习室时,他就从墙上拿钥匙(钥匙只有一把)解锁进入教室,而此时的自习室就是临界区,小明在自习室的书本,本子,笔就是临界资源,当小明突然要上厕所离开自习室时,因为自习室里有小明的书本呀,笔呀,等等东西,所以小明离开时就把门锁上了。小明自习了一天了,到晚上了吃饭了,小明不想自习了,小明带上他的东西离开,然后 把门锁上,把钥匙挂回墙上,此时其他同学就可以使用自习室了。在这例子中锁的作用就是只允许有钥匙的学生进入自习室,不允许其他没有钥匙的同学进入(其他线程),换言之锁的作用就是实现在一个临界区中的任一时刻只允许一个线程进入,访问。在这个故事中如果自习室门上没有锁,当小明要上厕所时,别的同学可以可以进入自习室破坏,拿走小明的东西呢?答案是有可能的,所以为了保证自习室里的小明的资源的安全,所以需要锁,把门上锁。

什么时候使用锁?

使用锁主要在多线程或多用户环境中,当多个线程或用户需要并发访问和修改共享资源时。锁能确保同一时间只有一个线程或用户访问资源,避免数据冲突和不一致。在需要保证数据完整性、原子性和安全性的场景下,应使用锁来同步和控制对共享资源的访问。

在Linux中锁长什么样呢?我们怎么定义锁呢?

pthread_mutex_t是一个用于线程同步的互斥锁类型。例如:pthread_mutex_t mutex:定义互斥锁变量mutex,mutex就是一个锁(锁变量)。

二、锁的接口

1.初始化锁

 

功能:用于初始化锁变量
原型

#include <pthread.h>

锁为局部变量时使用如下函数初始化

int pthread_mutex_init(pthread_mutex_t *restrict mutex,
              const pthread_mutexattr_t *restrict attr);

锁为全局变量时使用如下方法初始化

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 

参数

  1. pthread_mutex_t *restrict mutex:指向要初始化的互斥锁变量的指针。这个指针指向的互斥锁变量在调用 pthread_mutex_init 之前应该是未初始化的。

  2. const pthread_mutexattr_t *restrict attr:指向互斥锁属性的指针。这个参数是可选的,通常可以传递 NULL (nullptr)来使用默认的互斥锁属性。如果你需要设置特定的属性(例如互斥锁的类型),你需要先使用 pthread_mutexattr_init 初始化一个 pthread_mutexattr_t 变量,然后设置所需的属性,最后将其传递给 pthread_mutex_init

返回值:成功返回0;失败返回错误码

使用例子:

#include <iosteam>
#include <pthread.h>
using namespace std;//全局锁初始化方式
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;//定义并初始化锁int main()
{//局部初始化方式pthread_mutex_t local_mutex;//定义锁pthread_mutex_init(&local_mutex, nullptr);//初始化锁//加锁//...//解锁//销毁锁return 0;
}

 

2.加锁

功能:获取(锁定)互斥锁,如果锁当前未被其他线程占用(即锁是“空闲”的),那么调用此函数的线程将成功获取锁,并可以继续执行其临界区代码。如果锁已被其他线程占用,则调用线程将被阻塞,直到锁被释放(即被当前持有锁的线程调用 pthread_mutex_unlock
原型

#include <pthread.h>

int pthread_mutex_lock(pthread_mutex_t *mutex);

参数

pthread_mutex_t *mutex:是一个指向互斥锁变量的指针。

返回值

pthread_mutex_lock 函数的返回值用于指示加锁操作是否成功。

  • 如果成功获取锁,函数返回 0
  • 如果在尝试获取锁时发生错误(例如,由于无效的互斥锁指针或系统资源不足),函数将返回一个错误码(非零值)。具体的错误码可以根据不同的系统和库实现而有所不同,但通常会遵循 POSIX 线程标准中定义的错误码。

注意事项

  • 使用 pthread_mutex_lock 时,必须确保在不再需要锁时调用 pthread_mutex_unlock 来释放锁,以避免死锁。
  • 如果在调用 pthread_mutex_lock 后线程被中断或取消,锁可能仍然处于锁定状态,需要特别小心处理。
  • 如果互斥锁的类型是递归锁(recursive mutex),则同一个线程可以多次获取同一个锁,但每次获取锁后都必须对应地释放锁。

3.申请锁

功能:尝试获取一个互斥锁(mutex),而不会阻塞调用线程。如果互斥锁已经被其他线程持有,则 pthread_mutex_trylock 不会使调用线程进入睡眠状态等待锁释放,而是立即返回表示失败的错误码。
原型

#include <pthread.h>

int pthread_mutex_trylock(pthread_mutex_t *mutex);
参数

pthread_mutex_t *mutex:是一个指向互斥锁变量的指针。
返回值

  • 如果成功获取锁,函数返回 0
  • 如果锁已被其他线程占用,或者发生其他错误(如传递了无效的互斥锁指针),函数将返回一个错误码。常见的错误码包括 EBUSY(表示锁当前被其他线程占用)和 EINVAL(表示传递给函数的互斥锁是无效的)。

4.解锁

功能:用于释放互斥锁(mutex),在多线程编程中用于确保线程同步的正确性。当一个线程完成对共享资源的访问后,它应该调用 pthread_mutex_unlock 来释放锁,以便其他线程能够获取该锁并访问相同的资源。
原型

#include <pthread.h>

int pthread_mutex_unlock(pthread_mutex_t *mutex);

参数

pthread_mutex_t *mutex:是一个指向互斥锁变量的指针。
返回值

  • 如果成功释放锁,函数返回 0
  • 如果在尝试解锁时发生错误(例如,传递给函数的互斥锁是无效的,或者当前线程没有持有该锁),函数将返回一个错误码。常见的错误码包括 EINVAL(表示传递给函数的互斥锁是无效的)和 EPERM(表示当前线程没有持有该锁)。

5.销毁锁

功能:用于销毁(释放)互斥锁(mutex)的函数。在多线程编程中,当不再需要某个互斥锁时,应该调用 pthread_mutex_destroy 来销毁它,以释放相关资源。
原型

#include <pthread.h>

int pthread_mutex_destroy(pthread_mutex_t *mutex);

参数

pthread_mutex_t *mutex:是一个指向互斥锁变量的指针。
返回值

  • 如果成功销毁锁,函数返回 0
  • 如果在尝试销毁锁时发生错误(例如,传递给函数的互斥锁是无效的,或者锁仍被持有),函数将返回一个错误码。常见的错误码包括 EBUSY(表示锁当前被其他线程占用)和 EINVAL(表示传递给函数的互斥锁是无效的)。

三、实践(写代码):黄牛抢票

说明:用多线程模拟黄牛,常数模拟票

Makefile

test:test.ccg++ -o $@ $^ -std=c++11 -lpthread
PHONY:clean
clean:rm -f test;

test.cc

#include <iostream>
#include <string>
#include <unistd.h>
#include <pthread.h>
#include <vector>
using namespace std;
int ticket = 1000; // 一千张票
int threadnum = 5; // 黄牛数
// 定义全局锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *threadtask(void *args)
{while (ticket > 0){string name = static_cast<char *>(args);// 加锁pthread_mutex_lock(&mutex);cout << "我是: " << name << "我抢到了" << ticket << "号票" << endl;ticket--; // 票数--sleep(1);// 解锁pthread_mutex_unlock(&mutex);}return nullptr;
}
int main()
{// 五个黄牛vector<pthread_t> threads;for (int i = 0; i < threadnum; i++){pthread_t tid;char threadname[64];sprintf(threadname, "thraed-%d", i + 1);pthread_create(&tid, nullptr, threadtask, threadname);threads.push_back(tid);}void *ret;for (int i = 0; i < threads.size(); i++){pthread_join(threads[i], &ret);//等待线程,回收资源}// 销毁锁pthread_mutex_destroy(&mutex);return 0;
}

结果

全是5号线程抢到票,原因是Linux内核中的线程调度器根据线程的优先级、状态和其他因素来决定哪个线程应该被调度执行。如果某个线程的优先级高于其他线程,或者其状态更适合执行(例如,它已准备好运行并且没有受到阻塞),那么它就更有可能被调度器选中。你可以在你的linux中试试或许会有不同的结果。

0c1a3fe630b84286af006feae9802cef.png

 完结!!!

 

相关文章:

[Linux]互斥锁(什么是锁,为什么需要锁,怎么使用锁(接口),演示代码)

目录 一、锁的概念 一些需要了解的概念 什么是锁&#xff1f;为什么需要锁&#xff1f;什么时候使用锁&#xff1f;怎么定义锁&#xff1f; 二、锁的接口 1.初始化锁 2.加锁 3.申请锁 4.解锁 5.销毁锁 三、实践&#xff08;写代码&#xff09;&#xff1a;黄牛抢票 M…...

Web基础06-AJAX,Axios,JSON数据

目录 一、AJAX 1.概述 2.主要作用 3.快速入门 4.AJAX的优缺点 &#xff08;1&#xff09;优点 &#xff08;2&#xff09;缺点 5.同源策略 二、Axios 1.概述 2.快速入门 3.请求方式别名 三、JSON 1.概述 2.主要作用 3.基础语法 4.JSON数据转换 &#xff08;1…...

Java 文件序列化和反序列化

list序列化 /*** 序列化* param list* param filename* throws IOException*/public static void serializeList(List<Map<String, Object>> list, String filename) throws IOException {try (ObjectOutputStream oos new ObjectOutputStream(new FileOutputStre…...

NETLINK_ROUTE 与 NETLINK_SOCK_DIAG 的区别与用法

在 Linux 中&#xff0c;Netlink 是一种用于内核与用户空间之间通信的机制&#xff0c;通过不同的 Netlink 协议族&#xff08;family&#xff09;可以实现不同类型的通信。其中&#xff0c;NETLINK_ROUTE 和 NETLINK_SOCK_DIAG 是两种常用的 Netlink 协议族&#xff0c;它们具…...

docker yocto vscode

scode的docker插件怎么使用 vscode是一个基于VS Code的开发环境&#xff0c;它提供了一个Docker插件&#xff0c;可以帮助你在VS Code中使用Docker进行开发。下面是使用scode的Docker插件的步骤&#xff1a; 安装scode插件&#xff1a;在VS Code的扩展商店中搜索并安装scode插…...

使用ansible剧本进行lvm分盘

使用 Ansible 剧本&#xff08;Playbook&#xff09;进行 LVM 分区管理是一种自动化的方式&#xff0c;可以帮助管理员在多台主机上批量管理逻辑卷。 部署环境 3台主机&#xff0c;添加硬盘 ansible-galaxy collection install community.general 联网执行&#xff0c;下…...

【排序】快速排序

原理 对于一个数组x&#xff0c;快速排序流程如下&#xff1a; 确定分界点a&#xff0c;可以取x[l]、x[r]、x[l r / 2]、随机&#xff08;四种都可以&#xff09;调整区间&#xff0c;使得&#xff1a;区间被分成 < a 和 > a的两部分&#xff0c;左边 < a&#xff…...

Python大数据实践:selenium爬取京东评论数据

准备工作 selenium安装 Selenium是广泛使用的模拟浏览器运行的库&#xff0c;用于Web应用程序测试。 Selenium测试直接运行在浏览器中&#xff0c;就像真正的用户在操作一样&#xff0c;并且支持大多数现代 Web 浏览器。 #终端pip安装 pip install selenium #清华镜像安装 p…...

信息系统项目管理师019:存储和数据库(2信息技术发展—2.1信息技术及其发展—2.1.3存储和数据库)

文章目录 2.1.3 存储和数据库1.存储技术2.数据结构模型3.常用数据库类型4.数据仓库 记忆要点总结 2.1.3 存储和数据库 1.存储技术 存储分类根据服务器类型分为&#xff1a;封闭系统的存储和开放系统的存储。封闭系统主要指大型机等服务器。开放系统指基于包括麒麟、欧拉、UNIX…...

Python基础(六)之数值类型元组

Python基础&#xff08;六&#xff09;之数值类型元组 1、简介 元组&#xff1a; 在Python中是内置的数据结构之一&#xff0c;是一个不可变的序列,切可以是任何类型数据。元组的元素放在&#xff08;&#xff09;小括号内。一般我们希望数据不改变的时候使用 不可变与可变的…...

Chrome历史版本下载地址:Google Chrome Older Versions Download (Windows, Linux Mac)

最近升级到最新版本Chrome后发现页面居然显示错乱,是在无语, 打算退回原来的版本, 又发现官方只提供最新的版本下载, 为了解决这个问题所有收集了Chrome历史版本的下载地址分享给大家. Google Chrome Windows version 32-bit VersionSizeDate104.0.5112.10279.68 MB2022-05-30…...

ROS2纯跟踪实现(C++)

#include <tf2_ros/buffer.h> #include <tf2_ros/transform_broadcaster.h> #include <tf2_ros/transform_listener.h>#include <geometry_msgs/msg/transform_stamped.hpp> #include...

uniapp微信小程序随机生成canvas-id报错?

uniapp微信小程序随机生成canvas-id报错&#xff1f; 文章目录 uniapp微信小程序随机生成canvas-id报错&#xff1f;效果图遇到问题解决 场景&#xff1a; 子组件&#xff0c;在 mounted 绘制 canvas&#xff1b;App、H5端正常显示&#xff0c;微信小程序报错&#xff1b; 效…...

爬虫 Day2

resp.close()#关掉resp 一requests入门 &#xff08;一&#xff09; 用到的网页&#xff1a;豆瓣电影分类排行榜 - 喜剧片 import requestsurl "https://movie.douban.com/j/chart/top_list" #参数太长&#xff0c;重新封装参数 param {"type": "…...

达梦数据库SQL

达梦JSON函数技术文档 SQL中关键词处理 -- 必须要使用双引号包裹 select id,"comment" from t_cmp_rd_process;select id,"commit" from t_cmp_rd_gjj_eva;JSON_EXTRACT函数 -- party_sup_other_json 是包含JSON数据的列名。 -- $.content_abstract 是J…...

python教程——把视频转成gif

一、前言 很多网站提供视频转GIF的功能&#xff0c;但要么收费要么有广告&#xff0c;实际上可以通过python&#xff0c;几行代码就能够实现视频转gif。 二、使用方法 1安装必备库moviepy pip install moviepy -i https://pypi.tuna.tsinghua.edu.cn/simple 2. 写入代码 …...

深入浅出Go的`encoding/xml`库:实战开发指南

深入浅出Go的encoding/xml库&#xff1a;实战开发指南 引言基本概念XML简介Go语言中的XML处理结构体标签&#xff08;Struct Tags&#xff09; 解析XML数据使用xml.Unmarshal解析XML结构体标签详解处理常见解析问题 生成XML数据使用xml.Marshal生成XML使用xml.MarshalIndent优化…...

深度学习之扩散模型(Diffusion model)

代码解析&#xff1a;正向扩散过程和加噪演示 引言 这段代码实现了一个正向扩散过程和加噪演示的功能。通过生成一个特定形状的数据集&#xff0c;并在每个时间步长上应用正向扩散过程和加噪过程&#xff0c;最终展示了数据点在空间中的演变过程。 数据集生成 通过 make_swiss…...

Tomcat Session ID---会话保持

简单拓补图 一、负载均衡、反向代理 7-1nginx代理服务器配置 [rootdlnginx ~]#yum install epel-release.noarch -y ###安装额外源[rootdlnginx ~]#yum install nginx -y[rootdlnginx ~]#systemctl start nginx.service[rootdlnginx ~]#systemctl status nginx.service [ro…...

Session会话绑定

1.需求原因 用户的请求,登录的请求,经过负载均衡后落到后面的web服务器上,登录的状态/信息也会记录在web服务器上,就会导致不通的web服务器上,登录状态不统一,造成用户频繁需要登录 2.目标&#xff1a;如何实现会话保持/会话共享 方案一&#xff1a;登录状态写入cookie中.(wor…...

win7、win10、win11 系统能安装的.net framework 版本以

win7、win10、win11 系统能安装的.net framework 版本分别是多少&#xff1f;以及能安装的最高版本是多少&#xff1f; 以下是各Windows系统能够安装和支持的.NET Framework版本及其最高可安装版本的概述&#xff1a; Windows 7&#xff1a; 自带 .NET Framework 3.5.1&#x…...

RediSearch比Es搜索还快的搜索引擎

1、介绍 RediSearch是一个Redis模块&#xff0c;为Redis提供查询、二次索引和全文搜索。要使用RediSearch&#xff0c;首先要在Redis数据上声明索引。然后可以使用重新搜索查询语言来查询该数据。RedSearch使用压缩的反向索引进行快速索引&#xff0c;占用内存少。RedSearch索…...

mybatis-plus 的saveBatch性能分析

Mybatis-Plus 的批量保存saveBatch 性能分析 目录 Mybatis-Plus 的批量保存saveBatch 性能分析背景批量保存的使用方案循环插入使用PreparedStatement 预编译优点&#xff1a;缺点&#xff1a; Mybatis-Plus 的saveBatchMybatis-Plus实现真正的批量插入自定义sql注入器定义通用…...

python异常:pythonIOError异常python打开文件异常

1.python读取不存在的文件时&#xff0c;抛出异常 通过 open()方法以读“r”的方式打开一个 abc.txt 的文件&#xff08;该文件不存在&#xff09;&#xff0c;执行 open()打开一个不存在的文件时会抛 IOError 异常&#xff0c;通过 Python 所提供的 try...except...语句来接收…...

电话机器人语音识别用哪家更好精准度更高。

语音识别系统的选择取决于你的具体需求&#xff0c;包括但不限于识别精度、速度、易用性、价格等因素。以下是一些在语音识别领域表现较好的公司和产品&#xff1a; 科大讯飞&#xff1a;科大讯飞是中国最大的语音识别技术提供商之一&#xff0c;其语音识别技术被广泛应用于各…...

【Unity动画】Unity如何导入序列帧动画(GIF)

Unity 不支持GIF动画的直接播放&#xff0c;我们需要使用序列帧的方式 01准备好序列帧 02全部拖到Unity 仓库文件夹中 03全选修改成精灵模式Sprite 2D ,根据需要修改尺寸&#xff0c;点击Apply 04 创建一个空物体 拖动序列上去 然后全选所有序列帧&#xff0c;拖到这个空物体…...

uniapp APP 上传文件

/*** 上传文件*/uploadPhoneFile:function(callback,params {}) {let fileType [.pdf,.doc,.xlsx,.docx,.xls]// #ifdef APP-PLUSplus.io.chooseFile({title: 选择文件, filetypes: [doc, docx], // 允许的文件类型 multiple: false, // 是否允许多选 },(e)>{const tem…...

arcgis数据导出到excel

将arcgis属性数据导出到excel&#xff1a; 1&#xff09; 工具箱\系统工具箱\Conversion Tools.tbx\Excel\Excel 转表 2&#xff09;用excel打开导出的图层文件中后缀为.dbf的数据&#xff08;方便快捷&#xff0c;但是中文易乱码&#xff09;...

吴恩达深度学习环境本地化构建wsl+docker+tensorflow+cuda

Tensorflow2 on wsl using cuda 动机环境选择安装步骤1. WSL安装2. docker安装2.1 配置Docker Desktop2.2 WSL上的docker使用2.3 Docker Destop的登陆2.4 测试一下 3. 在WSL上安装CUDA3.1 Software list needed3.2 [CUDA Support for WSL 2](https://docs.nvidia.com/cuda/wsl-…...

R语言:microeco:一个用于微生物群落生态学数据挖掘的R包:第七:trans_network class

# 网络是研究微生物生态共现模式的常用方法。在这一部分中&#xff0c;我们描述了trans_network类的所有核心内容。 # 网络构建方法可分为基于关联的和非基于关联的两种。有几种方法可以用来计算相关性和显著性。 #我们首先介绍了基于关联的网络。trans_network中的cal_cor参数…...

wordpress没有上级目录的写权限/东莞网站营销推广

目录1、Jsoup是什么2、Jsoup解析URL返回结果3、Jsoup解析HTML片段1、Jsoup是什么 Jsoup是java的HTML解析器&#xff0c;可以解析请求URL的返回结果&#xff0c;可以解析HTML的片段内容&#xff0c;其实主要用来解析HTML内容的。 pom.xml文件引入&#xff1a; <!-- https:…...

wordpress 导航栏 搜索/微信小程序开发教程

规则 /* 1.从mongodb中取某个用户信息 2.根据用户年龄决定以下流程2-1 年龄小于18岁&#xff0c;进入防沉迷2-2 年龄大于18岁&#xff0c;验证身份证 3.根据不同等级的用户&#xff0c;展示不同页面 4.根据以上结果&#xff0c;进入游戏 */代码 function getUserInfoFromDB(u…...

设计接单网站大全/合肥网站维护公司

教你一个怎么看钢琴乐谱的绝招&#xff0c;钢琴乐谱怎么看&#xff1f;01认识五线谱及口诀高音谱号下加一线你唱1&#xff0c;下加一间你唱2一二三线&#xff0c;3 5 7&#xff0c;四线五线唱2 4&#xff0c;一二三间&#xff0c;4 6 1&#xff0c;&#xff0c;到了四间请唱 3上…...

南宁建站公司模板/南宁网站建设网站推广

小白学Django系列&#xff1a;小白学Django第一天| MVC、MVT以及Django的那些事日更中...用最短的时间学最多的知识&#xff0c;本文大约花费4分钟本文内容&#xff1a;1. 创建Django项目以及目录结构2. 创建应用和注册应用3. 测试服务器1. 创建Django项目以及目录结构创建Djan…...

.net php开发网站开发/百度手机助手网页版

安装在android系统中的每一个apk文件&#xff0c;Android给每个APK进程分配一个单独的用户空间&#xff0c;其manifest中的userid就是对应一个Linux用户id&#xff0c;之所以 分配单独的用户进程以防止apk影响其他应用程序&#xff08;或者其他应用程序影响它&#xff09;。用户…...

网站建设基础筹备/网络优化这个行业怎么样

CTSC/APIO2018滚粗记 前言 从\(5.5\)晚上的火车到\(5.14\)早上的高铁\(10\)天的时间真的过去的很快。 眨眼间&#xff0c;就到了今天晚上的颁奖。 至于结果如何&#xff0c;反而并不是那么重要了。 这次的比赛很明显的感受就是和全国的高手同台竞技&#xff0c; 不难感受到自己…...