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

news/2024/11/27 0:12:12/
  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.ppmy.cn/news/26073.html

相关文章

初识K8s

概览 k8s 概念和架构从零搭建K8s 集群k8s 核心概念搭建集群监控平台搭建高可用k8s集群集群环境 实际部署项目 k8s 概念和架构 1、K8S概述和特性 概述&#xff1a; k8s是谷歌在2014年开源的容器化集群管理系统使用k8s进行容器化应用部署使用k8s利于应用扩展k8s目标实施让部…

链表学习之反转链表

链表解题技巧 额外的数据结构&#xff08;哈希表&#xff09;&#xff1b;快慢指针&#xff1b;虚拟头节点&#xff1b; 反转链表 分别实现单向链表和双向链表的反转。 要求&#xff1a;长度为N的链表&#xff0c;时间复杂度为O(N)&#xff0c;额外空间复杂度为O(1)。 反转…

ClickHouse详解

一、概念ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。OLAP场景的关键特征绝大多数是读请求数据以相当大的批次(> 1000行)更新&#xff0c;而不是单行更新;或者根本没有更新。已添加到数据库的数据不能修改。对于读取&#xff0c;从数据库中提取相当多的…

【1237. 找出给定方程的正整数解】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个函数 f(x, y) 和一个目标结果 z&#xff0c;函数公式未知&#xff0c;请你计算方程 f(x,y) z 所有可能的正整数 数对 x 和 y。满足条件的结果数对可以按任意顺序返回。 尽管函数的具体式子…

Python学习笔记:条件、循环及其他语句

条件、循环及其他语句 赋值 赋值语句的右边可以是任何类型的序列&#xff0c;但带星号的变量最终包含的总是一个列表。 >>> a, *b, c "abc" >>> a, b, c (a, [b], c)这种收集方式也可用于函数参数列表中 条件语句 用作布尔表达式&#xff…

【Java基础】Java对象创建的几种方式

先上关键内容&#xff0c;所用到的代码请参考文末示例代码。一、使用new关键字创建对象这是一种最常用的创建对象的方式。Student student1 new Student();二、使用Class的newInstance()方法创建对象需要有一个无参构造方法&#xff0c;这个newInstance()方法调用无参的构造函…

Java反序列化漏洞——CommonsCollections4.0版本—CC2、CC4

一、概述4.0版本的CommonsCollections对之前的版本做了一定的更改&#xff0c;那么之前的CC链反序列化再4版本中是否可用呢。实际上是可用的&#xff0c;比如CC6的链&#xff0c;引入的时候因为⽼的Gadget中依赖的包名都是org.apache.commons.collections &#xff0c;⽽新的包…

【ArcGIS Pro二次开发】(5):UI管理_自定义控件的位置

新增的自定义控件一般放在默认的【加载项】选项卡下&#xff0c;但是根据需求&#xff0c;我们可能需要将控件放在新的自定义选项卡下&#xff0c;在自定义选项卡添加系统自带的控件&#xff0c;将自定义的按钮等控件放在右键菜单栏里以方便使用&#xff0c;等等。 下面就以一…