c++积累5-lock_guard使用

news2024/10/6 4:14:28

1、std:mutex

在了解lock_guard之前,需要先学习下std:mutex,因为lock_guard内部就是使用的std:mutex
std:mutex:是一个用于保护共享数据不会同时被多个线程访问的类,它叫做互斥量。我们可以把它看作一把锁,基本使用如下:

#include <mutex>

std::mutex kMutex;

void function() {
  //加锁
  kMutex.lock();
  //kMutex.try_lock();

  //do something that is thread safe...
  
  // 离开作用域解锁
  kMutex.unlock();
}

来看一个例子,两个线程共同访问一个全局变量
首先我们实现一个不加锁的看看有什么问题:


#include <iostream>
#include <thread>

int gData = 0;
std::mutex kMutex;

void increment(){
    for (int i = 0; i < 1000000; i++) {
        gData++;
        std::cout<< std::this_thread::get_id()  << ":"<< gData << std::endl;
    }
}

int main() {
    std::cout<< __FUNCTION__  << ":" << gData << std::endl;
    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    getchar();

    return 0;
}

输出:
在这里插入图片描述
可以看到,结果并不是我们所期望的,那么我们使用mutex加上锁之后看下:


#include <iostream>
#include <thread>

int gData = 0;
std::mutex kMutex;

void increment(){
    kMutex.lock();
    for (int i = 0; i < 1000000; i++) {
        gData++;
        std::cout<< std::this_thread::get_id()  << ":"<< gData << std::endl;
    }
    kMutex.unlock();
}

int main() {
    std::cout<< __FUNCTION__  << ":" << gData << std::endl;
    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    getchar();

    return 0;
}

输出:
在这里插入图片描述
我们可以看到加了锁之后呢,输出结果是正确的了

2、std:lock_guard

std:lock_guard 其实就是对std:mutex的一个包装类,能够实现自动unlock,而不必手动进行unlock操作。它在构造中完成加锁,在析构中完成解锁。
先让我们自己实现一个这样的类:

namespace myspace{
    template<typename T> class my_lock_guard{
    public:
        my_lock_guard(T& mutex):mutex_(mutex){
            // 构造加锁
            mutex_.lock();
        }

        ~my_lock_guard(){
            // 析构解锁
            mutex_.unlock();
        }

    private:
        // 不可赋值,不可拷贝
        my_lock_guard(my_lock_guard const&);
        my_lock_guard& operator=(my_lock_guard const&);

    private:
        T& mutex_;
    };
}

还是按照上面小节中的例子:


#include <iostream>
#include <thread>

int gData = 0;
std::mutex kMutex;

namespace myspace{
    template<typename T> class my_lock_guard{
    public:
        my_lock_guard(T& mutex):mutex_(mutex){
            // 构造加锁
            mutex_.lock();
        }

        ~my_lock_guard(){
            // 析构解锁
            mutex_.unlock();
        }

    private:
        // 不可赋值,不可拷贝
        my_lock_guard(my_lock_guard const&);
        my_lock_guard& operator=(my_lock_guard const&);

    private:
        T& mutex_;
    };
}

void increment(){
    myspace::my_lock_guard<std::mutex> myLockGuard(kMutex);

    for (int i = 0; i < 1000000; i++) {
        gData++;
        std::cout<< std::this_thread::get_id()  << ":"<< gData << std::endl;
    }
}

int main() {
    std::cout<< __FUNCTION__  << ":" << gData << std::endl;
    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    getchar();

    return 0;
}

输出:
在这里插入图片描述
可以看到这里的输出也是正确的。

std::lock_guard原理跟这个也是一样的,我们看下它的源码:
在这里插入图片描述
例子代码:


#include <iostream>
#include <thread>

int gData = 0;
std::mutex kMutex;

namespace myspace{
    template<typename T> class my_lock_guard{
    public:
        my_lock_guard(T& mutex):mutex_(mutex){
            // 构造加锁
            mutex_.lock();
        }

        ~my_lock_guard(){
            // 析构解锁
            mutex_.unlock();
        }

    private:
        // 不可赋值,不可拷贝
        my_lock_guard(my_lock_guard const&);
        my_lock_guard& operator=(my_lock_guard const&);

    private:
        T& mutex_;
    };
}

void increment(){
    std::lock_guard<std::mutex> lockGuard(kMutex);

    for (int i = 0; i < 1000000; i++) {
        gData++;
        std::cout<< std::this_thread::get_id()  << ":"<< gData << std::endl;
    }
}

int main() {
    std::cout<< __FUNCTION__  << ":" << gData << std::endl;
    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    getchar();

    return 0;
}

输出:
在这里插入图片描述
看结果也是正确的。

总结三个代码在例子中的不同处:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【致敬未来的攻城狮计划】— 连续打卡第四天:e2 studio 使用教程

系列文章目录 1.连续打卡第一天&#xff1a;提前对CPK_RA2E1是瑞萨RA系列开发板的初体验&#xff0c;了解一下 2.开发环境的选择和调试&#xff08;从零开始&#xff0c;加油&#xff09; 3.欲速则不达&#xff0c;今天是对RA2E1 基础知识的补充学习。 文章目录 系列文章目录 文…

Flutter成不了“顶流明星”的7大理由

Flutter是一款由Google推出的跨平台移动应用开发框架&#xff0c;近年来备受关注。尽管Flutter在某些方面表现出色&#xff0c;但仍然有一些人对它的发展前景表示怀疑。近期一些文章针对Flutter的发展提出了不少质疑和批评&#xff0c;称其难以成为移动应用开发的“顶流明星”&…

【计算机网络—— 安装packet tracer的教程,管理MAC地址和配置路由器的实验步骤以及心得体会】

文章目录安装packet tracer的教程管理MAC地址实验目的 &#xff1a;管理MAC地址实验内容及过程记录&#xff08;一&#xff09;运行Cisco Packet Tracer软件&#xff08;二&#xff09;选择PC终端&#xff08;三&#xff09;运行终端&#xff08;四&#xff09;按表内容对交换机…

Spring Cloud Nacos使用总结

目录 安装Nacos服务器 服务发现与消费 服务发现与消费-添加依赖 服务发现-配置文件 服务发现-注解 服务发现-Controller 服务消费-配置文件 服务消费-注解与Ribbon消费代码 服务消费-运行 配置管理 配置管理-添加依赖 配置管理-配置文件 配置管理-注解 配置管理-…

Raft一致性算法(精简和扩展)

raft一致性算法 文章目录raft一致性算法一、raft简介1.1 raft涉及到的名词1.2 Rpc请求1.3 复制状态机二、raft⼀致性算法2.0 摘要2.0.1 所有服务器需遵守的规则2.0.2 跟随者2.0.3 候选⼈2.0.4 领导人2.0.5 状态2.0.6 特性2.1 raft基础2.2 leader选举2.2.1 集群启动时选举2.2.2 …

微电网两阶段鲁棒优化经济调度方法(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

清华大学ChatGLM-6B部署运行

一、模型介绍 开源项目&#xff1a; GitHub - THUDM/ChatGLM-6B: ChatGLM-6B&#xff1a;开源双语对话语言模型 | An Open Bilingual Dialogue Language Model ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型&#xff0c;基于 General Language Model (GLM) 架构&…

PLC高精度定时器(T法测速功能块)

S7-200 SMART PLC时间间隔指令BGN_ITIME,和CAL_ITIME采用的是系统自带的1ms高精度定时器,PLC里只能调用一次。T法测速和M法测速应用时,都需要高精度时序定时器的支持(当然你也可以采用定时中断的方式获取高精度时序),时间间隔指令请参看下面的博客文章: SMART PLC时间间…

keil5使用c++编写stm32控制程序

keil5使用c编写stm32控制程序一、前言二、配置图解三、std::cout串口重定向四、串口中断服务函数五、结尾废话一、前言 想着搞个新奇的玩意玩一玩来着&#xff0c;想用c编写代码来控制stm32&#xff0c;结果在keil5中&#xff0c;把踩给我踩闷了&#xff0c;这里简单记录一下。…

FlinkSQL的Watermark机制和Checkpoint机制

Watermark机制 Watermark机制&#xff0c;就是水印机制&#xff0c;也叫做水位线机制。就是专门用来解决流式环境下数据迟到问题的。 MonotonousWatermark&#xff08;单调递增水印&#xff09; package day05;import lombok.AllArgsConstructor; import lombok.Data; impor…

【谷粒商城之JSR303数据校验和集中异常处理】

本笔记内容为尚硅谷谷粒商城JSR303数据校验和集中异常处理部分 目录 一、简介 二、SR303数据校验使用步骤 1、引入依赖 2、给参数对象添加校验注解 常见的注解 3、接口参数前增加Valid 开启校验 三、异常的统一处理 四、分组解决校验 1、创建Groups 2、添加分组 …

MySQL数据库之表的增删改查(进阶)

目录1. 数据库约束1.1 约束类型1.2 NULL约束1.3 UNIQUE&#xff1a;唯一约束1.4 DEFAULT&#xff1a;默认值约束1.5 PRIMARY KEY&#xff1a;主键约束1.6 FOREIGN KEY&#xff1a;外键约束1.7 CHECK约束2 表之间的关系2.1 一对一2.2 一对多2.3 多对多3 新增4 查询4.1 聚合查询4…

Redis一致性问题

&#xff08;1&#xff09;何为一致性&#xff1f; 1、定义&#xff1a; 指系统中各节点数据保持一致。 分布式系统中&#xff0c;可以理解为多个节点中的数据是一致的。 2、分类&#xff1a; 强一致性&#xff1a;写进去的数据是什么&#xff0c;读出来的数据就是什么。弱一…

DeepSpeed-Chat:最强ChatGPT训练框架,一键完成RLHF训练!

https://github.com/microsoft/DeepSpeedExamples/tree/master/applications/DeepSpeed-Chat 一个快速、负担得起、可扩展和开放的系统框架&#xff0c;用于实现端到端强化学习人类反馈 (RLHF) 培训体验&#xff0c;以生成各种规模的高质量 ChatGPT 样式模型。 目录 &#x…

计算机体系结构-体系结构基础与流水线原理

计算机体系结构&#xff1a;体系结构基础与流水线原理 ​ 计算机体系结构&#xff1a;量化设计与分析一书以RISC-V为例介绍计算机体系结构。本文为第一部分&#xff0c;介绍体系结构的基本知识和流水线原理。笔记内容为原书的第一章&#xff0c;附录A、B、C。 第一章 量化设计…

练习Tomcat

文章目录1. 简述静态网页和动态网页的区别。2. 简述 Webl.0 和 Web2.0 的区别。3. 安装tomcat8&#xff0c;配置服务启动脚本&#xff0c;部署jpress应用。1. 简述静态网页和动态网页的区别。 静态网页&#xff1a; &#xff08;1&#xff09;静态网页不能简单地理解成静止不…

SCADE Display(OpenGL)软件设计文档生成工具的设计考虑

SCADE Display&#xff08;OpenGL&#xff09;软件设计文档生成工具的设计考虑 2018年6月 1 引言 本文档描述在SCADE Display软件设计文档生成工具&#xff08;以下简称为SDYSDDGEN&#xff09;的设计过程中考虑到的一些问题及其解决方案。 2 目标 SDYSDDGEN的目标设定为&…

面向对象程序设计 C++总结笔记(1)

面向对象程序设计 学习方法 理解基本原理掌握程序设计方法加强动手实践 课程目标 理解面向对象程序设计的基本原理&#xff0c;掌握面向对象技术的基本概念和封装性、继承性和多态性&#xff0c;能够具有面向对象程序设计思想。掌握C语言面向对象的基本特性和C语言基础知识&…

就在20号!袋鼠云春季生长大会邀您共观数智生机,我们云上见

如今&#xff0c;数字经济正逐步走向深化应用、规范发展、普惠共享的新阶段&#xff0c;数字经济与实体经济深度融合、基础软件国产化替代成为数字时代主潮流。 「 2023 袋鼠云春季生长大会」乘风而起&#xff0c;带您走近大数据基础软件——数栈&#xff0c;低代码数字孪生世界…

Hadoop之Yarn篇

目录 ​编辑 Yarn的工作机制&#xff1a; 全流程作业&#xff1a; Yarn的调度器与调度算法&#xff1a; FIFO调度器&#xff08;先进先出&#xff09;&#xff1a; 容量调度器&#xff08;Capacity Scheduler&#xff09;&#xff1a; 容量调度器资源分配算法&#xff1…