Linux--线程的互斥

线程系列:
一、线程的认识:线程的认识:误进解线程的概念和线程的基本控制
二、Linux–线程的分离、线程库的地址关系的理解、线程的简单封装

线程的互斥

线程互斥(Thread Mutual Exclusion)是多线程编程中的一个重要概念,它指的是在任意时刻只允许一个线程访问某一共享资源。这是为了避免多个线程同时访问和修改同一资源,从而导致数据不一致或其他不可预知的问题。

#include<iostream>
#include<vector>
#include"Thread.hpp"
#include<unistd.h>
#include<pthread.h>
using namespace ThreadMdule;
int g_tickets=1000;
class ThreadData
{
public:
    ThreadData(int& tickets,const string& name,pthread_mutex_t& mutex)
    :_tickets(tickets),_name(name),_total(0),_mutex(mutex)
    {

    }
    ~ThreadData(){}
public:
    int &_tickets;//所有线程都会引用到这个全局变量
    string _name;
    int _total;
    pthread_mutex_t& _mutex;
};
void route(ThreadData* td)
{
    while(true)
    {
        //pthread_mutex_lock(&gmutex);//加锁
       
        if(td->_tickets>0)
        {
            usleep(10000);
            printf("get tickets:%d\n",td->_tickets);
            td->_tickets--;
            //pthread_mutex_unlock(&gmutex);//过了临界区解锁
            td->_total++;
        }
        else
        {
            //pthread_mutex_unlock(&gmutex);
            break;
        }
    }
}

const int num=4;
int main()
{
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex,nullptr);

    vector<Thread<ThreadData*>> threads;
    vector<ThreadData*> datas;
    //创建新线程
    for(int i=0;i<num;i++)
    {
        string name="thread"+to_string(i + 1);
        ThreadData* td=new ThreadData(g_tickets,name,mutex);
        threads.emplace_back(route,td,name);
        datas.emplace_back(td);
    }
    //启动进程
    for(auto& thread:threads)
    {
        thread.start();
    }

    //等待进程结束
    for(auto& thread:threads)
    {
        thread.Join();
        cout<<"wait thread done,thread is: "<<thread.name()<<endl;
    }
    //统计数据
    for(auto data: datas)
    {
        cout<<data->_name<<" : "<<data->_total<<endl;
        delete data;
    }
    pthread_mutex_destroy(&mutex);
    return 0;
}

共享资源:每个线程可以同时访问的数据或其他资源。程序给出1000张票,让线程来模拟抢票,
在这里插入图片描述
在这里插入图片描述

总票数g_tickets会从内存中加载到CPU中进行逻辑运算,由于我们的线程没有进行保护,也就是说当票数只有一张的时候,所有线程运行时没有时间先后,是并行运行的;
所以剩1张票时4个线程都在抢,京就会出现负数的情况;我们看到每个线程最后的抢票总数,也是相对平均的,说明是并行运行的;

如何解决互斥问题?

先说一个概念:

临界资源(Critical Resource)是指在多线程或多进程环境中,一次只能被一个线程或进程安全访问的资源。这种资源如果被多个执行流同时访问,可能会导致数据不一致、数据损坏或其他未定义的行为。
在这里插入图片描述

临界资源通常是全局变量、共享数据结构(如链表、树、图等)、文件、网络连接、硬件设备或其他需要被多个执行线程或进程共享的资源。为了避免竞争条件和数据不一致,对临界资源的访问必须受到严格的控制。

为了保护临界资源,程序员通常会使用同步机制来确保在任何时候只有一个执行线程可以访问这些资源;

而使用互斥锁,就是实现同步机制的其中一种常见方法:
互斥锁(Mutex)一种简单的锁定机制,用于保护临界资源。当一个线程拥有互斥锁时,其他试图获取该锁的线程将被阻塞,直到锁被释放

互斥锁有关函数

在Linux中,线程互斥锁(Mutex)通常是通过POSIX线程库(pthread)来实现的。以下是与线程互斥锁相关的主要函数:

  1. pthread_mutex_init: 初始化互斥锁。
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
  • mutex:指向要初始化的互斥锁对象的指针。
  • attr:指定互斥锁属性的对象,如果传递NULL,则使用默认的互斥锁属性。
  1. pthread_mutex_destroy: 销毁互斥锁。
int pthread_mutex_lock(pthread_mutex_t *mutex);
  • mutex:指向要锁定的互斥锁对象的指针。
  1. pthread_mutex_lock: 锁定互斥锁.
int pthread_mutex_lock(pthread_mutex_t *mutex);
  • mutex:指向要锁定的互斥锁对象的指针。
  1. pthread_mutex_unlock: 解锁互斥锁。
 `int pthread_mutex_unlock(pthread_mutex_t *mutex);
  • mutex:指向要解锁的互斥锁对象的指针。
  1. pthread_mutex_trylock: 尝试锁定互斥锁,不会阻塞。
int pthread_mutex_trylock(pthread_mutex_t *mutex);
  • mutex:指向要尝试锁定的互斥锁对象的指针

定义全局锁

在这里插入图片描述

在这里插入图片描述

使用初始化和销毁来实现

在这里插入图片描述
在这里插入图片描述

线程互斥的底层实现

互斥锁是通过原子操作实现的。原子操作是不间断的单个指令,确保在执行过程中不被中断。
在这里插入图片描述
体系结构会提供一个swap或exchange的指令,该指令作用是将内存单元(mutex)和CPU上的寄存器进行数据交换,由于只有一条指令,保证了原子性。当某一个线程执行了这条指令,也就代表临界区被锁住了,那么只有当前这个线程能够过这个临界区,这就实现了对临界资源的保护。

只需要通过一条指令即可实现互斥锁:这是因为当数据在内存中时,所有线程都是可以访问的,属于共享的。如果转移到CPU内部寄存器时,那么这样就变成了私有了!!例如thread1先实现了交换指令,那么对于thread1线程来说寄存器1是私有的,对于临界区仍然可以执行;thread2也想实现临界区的内容,但由于共享资源被锁住,寄存器2又没有交换后的内容,所以thread2无法执行临界区的内容,只能等待thread1解锁后才能得到互斥锁;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件测试进阶

目录 一、自动化测试 1.概念 2.Selenium 2.1 概念 2.1.1 Selenium是什么&#xff1f; 2.1.2 Selenium特点 2.1.3 工作原理 2.2 SeleniumJava环境搭配 2.3 定位元素 2.3.1 CSS语法 2.3.2 XPath语法 2.4 应用 2.4.1 点击提交文本 2.4.2 模拟输入 2.4.3 清除文本 2…

驰骋低代码开发平台概念与主张

驰骋低代码开发平台概念与主张 一、引言 在数字化转型的浪潮中&#xff0c;低代码开发平台因其高效、灵活、成本效益显著的特点&#xff0c;逐渐成为企业快速构建应用系统的首选。作为国内领先的开源低代码开发平台&#xff0c;驰骋低代码致力于为企业和开发者提供一套全面、…

(南京观海微电子)——屏幕材质及优缺点对比

LED/LCD LCD&#xff08;Liquid Crystal Ddisplay&#xff09;即“液晶显示器”&#xff0c;由两块偏光镜、两块薄膜晶体管以及彩色滤光片、光源&#xff08;荧光灯&#xff09;、显示面板组成的成像元器件。 LED&#xff08;Light Emitting Diode&#xff09;即“发光二极管…

冒泡排序与快速排序

博主主页: 码农派大星. 数据结构专栏:Java数据结构 数据库专栏:MySQL数据库 关注博主带你了解更多数据结构知识 1.冒泡排序 冒泡排序 private static void swap(int[] arrary,int i,int j){int tmp arrary[i];arrary[i] arrary[j];arrary[j] tmp;public static void bubbl…

[docker] docker 安全知识 - docker api, 权限提升 资源管理

[docker] docker 安全知识 - docker api, 权限提升 & 资源管理 这是 docker 安全的最后一篇 暴露 docker api 在 [docker] docker 安全知识 - docker 系统性简介 中曾经提到&#xff0c;docker cli 使用 restful api 与客户端和 docker daemon 之间交流。默认情况下&…

国内的期权模拟账户怎么申请?

国内的期权模拟账户可以在券商和期权分仓平台处申请开通&#xff0c;期权相比于股票具有杠杆投资、风险控制等新特性。 期权模拟交易客户端能够提供期权的开平仓交易、备兑开仓&#xff0f;平仓、行权等交易指令&#xff0c;下文为大家介绍国内的期权模拟账户怎么申请&#xff…

安卓模拟键盘蓝牙电脑apk

蓝牙连接电脑就可以使用了。 下载地址&#xff1a;点击下载https://download.csdn.net/download/jasonhongcn/89382597

【基础算法总结】模拟算法

模拟算法 1.替换所有的问号2.提莫攻击3.Z 字形变换4.外观数列5.数青蛙 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x1f603; 模拟算法 —> 比葫芦…

npm发布、更新、删除包

如何将自己开发的依赖包发布到npmjs上供别人使用&#xff1f;五个步骤搞定&#xff01; 实现步骤&#xff1a; 创建自己的工具包项目&#xff0c;进行开发。注册npmjs账号。执行npm login在控制台登录&#xff0c;填写用户信息。执行npm publish发布包。更新及删除。 步骤一…

Leetcode - 周赛399

目录 一&#xff0c;3162. 优质数对的总数 I 二&#xff0c;3163. 压缩字符串 III 三&#xff0c;3164. 优质数对的总数 II 四&#xff0c; 3165. 不包含相邻元素的子序列的最大和 一&#xff0c;3162. 优质数对的总数 I 假设 x 是 nums1 数组中的值&#xff0c;y 是 nums2…

Docker部署SiYuan笔记-Unraid

使用unraid的docker部署SiYuan笔记&#xff0c;简单记录 笔记说明 Siyuan笔记是一款基于markdown语法的笔记工具&#xff0c;具有活跃的社区和多设备支持。大部分功能都是免费&#xff0c;源代码开源&#xff0c;支持插件安装&#xff0c;具有很不错的使用体验。 Docker地址&a…

【应用层】 DNS 域名协议解析

文章目录 DNS(Domain Name System)出现及演化 ⏳DNS 概括&#x1f50d;DNS定义DNS 作用 DNS工作原理⚙️域名解析DNS解析的详细工作流程 DNS域名解析方式&#x1f504;静态DNS域名解析动态DNS域名解析 DNS域名解析过程的深入分析 &#x1f9d0;递归查询迭代查询 公共DNS服务器的…

Python 机器学习 基础 之 处理文本数据 【停用词/用tf-idf缩放数据/模型系数/多个单词的词袋/高级分词/主题建模/文档聚类】的简单说明

Python 机器学习 基础 之 处理文本数据 【停用词/用tf-idf缩放数据/模型系数/多个单词的词袋/高级分词/主题建模/文档聚类】的简单说明 目录 Python 机器学习 基础 之 处理文本数据 【停用词/用tf-idf缩放数据/模型系数/多个单词的词袋/高级分词/主题建模/文档聚类】的简单说明…

AI帮写:探索国内AI写作工具的创新与实用性

随着AI技术的快速发展&#xff0c;AI写作正成为创作的新风口。但是面对GPT-4这样的国际巨头&#xff0c;国内很多小伙伴往往望而却步&#xff0c;究其原因&#xff0c;就是它的使用门槛高&#xff0c;还有成本的考量。 不过&#xff0c;随着GPT技术的火热&#xff0c;国内也涌…

Keras深度学习框架实战(3):EfficientNet实现stanford dog分类

1、通过EfficientNet进行微调以实现图像分类概述 通过EfficientNet进行微调以实现图像分类&#xff0c;是一个使用EfficientNet作为预训练模型&#xff0c;并通过微调&#xff08;fine-tuning&#xff09;来适应特定图像分类任务的过程。一下是对相关重要术语的解释。 Effici…

【气象常用】剖面图

效果图&#xff1a; 主要步骤&#xff1a; 1. 数据准备&#xff1a;我用的era5的散度数据&#xff08;大家替换为自己的就好啦&#xff0c;era5数据下载方法可以看这里【数据下载】ERA5 各高度层月平均数据下载_era5月平均数据-CSDN博客&#xff09; 2. 数据处理&#xff1a…

高考试卷押运车视频监控解决方案

一、引言 高考作为我国教育领域的重要事件&#xff0c;其公正、公平和安全性一直备受社会关注。试卷押运作为高考的重要环节&#xff0c;其安全性直接关系到高考的顺利进行和考生的切身利益。因此&#xff0c;对高考试卷押运车实施视频监控解决方案&#xff0c;对于确保试卷安…

【Pr学习】01新建项目起步

【Pr学习】01新建项目起步 1、新建项目2.序列设置2.1新建序列2.2序列参数讲解2.3自定义设置 3.PR窗口认识3.1 项目窗口3.2 源窗口2.4 保存面板 4.剪辑导入4.1 素材导入4.2 视图切换4.3 时间轴4.4轨道工具4.5 节目窗口素材导入 5.基础操作5.1 取消视频音频链接5.2 单独渲染&…

在不受支持的 Mac 上安装 macOS Sonoma (OpenCore Legacy Patcher v1.5.0)

在不受支持的 Mac 上安装 macOS Sonoma (OpenCore Legacy Patcher v1.5.0) Install macOS on unsupported Macs 请访问原文链接&#xff1a;https://sysin.org/blog/install-macos-on-unsupported-mac/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主…

Hugging Face称检测到对其人工智能模型托管平台的“未经授权访问“

周五下午晚些时候&#xff0c;人工智能初创公司Hugging Face表示&#xff0c;其安全团队在本周早些时候检测到对Spaces的"未经授权访问"&#xff0c;Spaces是Hugging Face用于创建、共享和托管人工智能模型和资源的平台。 Hugging Face 在一篇博文中说&#xff0c;这…