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

【Linux 多线程互斥】如何保证锁的原子性(互斥的原理)

  1. 临界资源:可以被多个执行流(线程或者叫轻量级进程)同是访问的(多个执行流共享的,比如:全局、堆等等);
  2. 临界区:访问这些临界资源的代码;
  3. 原子性:没有中间态,不做或者做完;

1.展示没有互斥的程序 

1.1.一个购票系统,有5个线程在购票

#include<iostream>
#include<cstdio>
#include<unistd.h>
#include<pthread.h>int tickets=100;
void* thread_run(void* args)
{int tmp=*((int*)args);while(1){if(tickets>0)//购表{usleep(10000);tickets--;printf("我是%d线程,还剩%d\n",tmp,tickets);}else{printf("没票了\n");break;}}return (void*)0;
}
int main()
{pthread_t tid[5];for(int i=0;i<5;i++)//创建5个线程{int* t=new int(i);pthread_create(tid+i,NULL,thread_run,(void*)t);}for(int i=0;i<5;i++){pthread_join(tid[i],NULL);}return 0;
}

执行结果:不是每次都会产生这样的结果 ,把票购成负数了不合理

 原理:

 2.互斥

互斥整个过程:保持临界资源的原子性

pthread_mutex_t lock;//锁

pthread_mutex_init(&lock,NULL);//初始化

pthread_mutex_lock(&lock);//加锁

//临界区

pthread_mutex_unlock(&lock);//解锁

pthread_mutex_destroy(&lock);//删除锁

 修改上面代码

#include<iostream>
#include<cstdio>
#include<unistd.h>
#include<pthread.h>pthread_mutex_t lk;//锁
int tickets=100;
void* thread_run(void* args)
{int tmp=*((int*)args);while(1){pthread_mutex_lock(&lk);//加锁if(tickets>0){usleep(10000);tickets--;printf("我是%d线程,还剩%d\n",tmp,tickets);}else{printf("没票了\n");pthread_mutex_unlock(&lk);//解锁break;}pthread_mutex_unlock(&lk);//解锁}return (void*)0;
}
int main()
{pthread_mutex_init(&lk,NULL);//初始化pthread_t tid[5];for(int i=0;i<5;i++){int* t=new int(i);pthread_create(tid+i,NULL,thread_run,(void*)t);}for(int i=0;i<5;i++){pthread_join(tid[i],NULL);}pthread_mutex_destroy(&lk);//删除锁return 0;
}

3.如何保证锁的原子性(互斥的原理)

为了实现互斥锁操作,大多数体系结构都提供了swap或exchange指令(汇编):作用是把寄存器和内存单元的数据相交换

过程:每一个线程调用lock,会先把自己上下文中关于锁的变量设为0,然后和使用一行代码(原子性)交换上下文的数据和锁的数据,锁的数据被换走变成0,其它线程来交换还是0,会挂起等待循环这个过程,直到换走数据的线程解锁为止;

 如果交换走锁数据的线程时间片到了,被调度那么它也是抱着锁走的,其他线程还是不能执行临界资源

http://www.lryc.cn/news/11008.html

相关文章:

  • Android 实现沉浸式全屏
  • 数据分析与SAS学习笔记6
  • 自动化完成1000个用户的登录并获取token并生成tokens.txt文件
  • 2023年全国最新安全员精选真题及答案1
  • NoMachine 输入用户名密码后 闪断 解决办法
  • WebADI - 参数的使用
  • 【OJ】两个圆
  • 一文读懂澳洲医疗:白菜价的药物怎么领?
  • scrum看板视图切换时间线视图做项目管理
  • 10、MySQL查询优化
  • C++模板(一)
  • 【TypeScript】TypeScript的基础类型(string,number,boolean,void,null,undefined):
  • 【C语言】 详谈指针
  • 内网渗透(三十八)之横向移动篇-pass the key 密钥传递攻击(PTK)横向攻击
  • 教你快速学会画动漫人物表情
  • Qt系列:调用Edge浏览器示例
  • 内推|香港外企急招ETL工程师!数据分析师+Python开发+运营专家
  • zlib压缩原理
  • 论文阅读笔记《DEEP GRAPH MATCHING CONSENSUS》
  • 华为OD机试题 - 开放日活动(JavaScript)
  • (考研湖科大教书匠计算机网络)第四章网络层-第八节:网际控制报文协议ICMP
  • 华为OD机试 - GPU 调度 | 备考思路,刷题要点,答疑 【新解法】
  • 华为OD机试题 - 任务总执行时长(JavaScript)
  • 还在想假期去哪玩?直接做一个旅游攻略小程序
  • 十四、vue3项目如何使用three.js
  • python 向excel表中添加新的sheet页或者向旧sheet中写入数据
  • RPC-grpc实践
  • JavaEE——MyBatis配置文件的详细介绍
  • bwmarrin/snowflake生成ID重复问题排查记录
  • 操作系统题目收录(十)