C++ 并发专题 - 不变式与多线程

一:概述

        在C++中,“不变式”通常是指程序中某些必须始终成立的条件或者规则,破坏不变式(breaking Invariant Solved)的问题通常出现在并发编程中,当多个线程同时操作共享数据时,如果没有正确同步,可能导致数据不一致,进而违反了不变式。 

        在多线程程序中,不变式是指那些在整个程序运行过程中始终需要保持为真的条件或属性。比如:

        1. 某个变量的值不能超过特定范围。

        2. 一个计数器的值应该是非负数。

        3. 某个状态应该在任何时候都保持一致。 

二:例子(账户总余额不变)

#include <atomic>
#include <functional>
#include <iostream>
#include <mutex>
#include <thread>struct Account
{int balance{ 100 };
};std::mutex mutAccount;void transferMoney(int amount, Account& from, Account& to)
{using namespace std::chrono_literals;{std::lock_guard<std::mutex> lock(mutAccount);if (from.balance >= amount){from.balance -= amount;std::this_thread::sleep_for(10ns);to.balance += amount;}}
}void printSum(Account& a1, Account& a2)
{std::lock_guard<std::mutex> lock(mutAccount);std::cout << (a1.balance + a2.balance) << '\n';
}int main()
{std::cout << '\n';Account acc1; Account acc2;std::cout << "initial sum: "; printSum(acc1, acc2);std::thread thr1(transferMoney, 5, std::ref(acc1), std::ref(acc2));std::thread thr2(transferMoney, 13, std::ref(acc2), std::ref(acc1));std::cout << "Intermediate sum: ";std::thread thr3(printSum, std::ref(acc1), std::ref(acc2));thr1.join();thr2.join();thr3.join();std::cout << "  acc1.balance: " << acc1.balance << '\n';std::cout << "  acc2.balance: " << acc2.balance << '\n';std::cout << "Final sum: "; printSum(acc1, acc2);std::cout << '\n';}

三: 破坏不变式的情况和示例

        破坏不变式通常发生在多线程程序中,尤其是当多个线程访问共享数据时,如果没有正确同步,可能会导致以下问题:

        1. 竞态条件:多个线程同时读写共享数据而没有适当的同步机制,导致数据不一致。

        2. 死锁:多个线程在等待对方释放资源时,导致程序无法继续运行。

        3. 不一致的状态:即使没有竞态条件,线程在更新数据时的时序问题可能导致不变式被破坏。

        下面介绍一个例子,多线程程序中,如果没有同步机制,共享变量会导致不一致的情况:

#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx;
int shared_value = 0;void increment() {for (int i = 0; i < 100000; ++i) {shared_value++;}
}void decrement() {for (int i = 0; i < 100000; ++i) {shared_value--;}
}int main() {std::thread t1(increment);std::thread t2(decrement);t1.join();t2.join();// 期望 shared_value 为 0,但由于缺少同步,可能不为 0std::cout << "Shared value: " << shared_value << std::endl;return 0;
}

四:解决不变式破坏问题的方法: 

        解决不变式被破坏问题的方法通常涉及到正确的线程同步,可以使用 std::mutex 来确保同一时刻只有一个个线程访问共享资源,从而避免竞态条件。以下是解决上述问题的示例代码:

#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx;
int shared_value = 0;void increment() {for (int i = 0; i < 100000; ++i) {std::lock_guard<std::mutex> lock(mtx);  // 使用锁来保护共享资源shared_value++;}
}void decrement() {for (int i = 0; i < 100000; ++i) {std::lock_guard<std::mutex> lock(mtx);  // 使用锁来保护共享资源shared_value--;}
}int main() {std::thread t1(increment);std::thread t2(decrement);t1.join();t2.join();// 现在,shared_value 应该是 0std::cout << "Shared value: " << shared_value << std::endl;return 0;
}

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

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

相关文章

Oh My Posh安装

nullSet up your terminalhttps://ohmyposh.dev/docs/installation/windows Git ee oh-my-posh: Windows上的oh-my-zsh&#xff0c;源地址 https://github.com/JanDeDobbeleer/oh-my-posh.git (gitee.com)https://gitee.com/efluent/oh-my-posh

MySQL 安装

所有平台的 MySQL 下载地址为&#xff1a; MySQL 下载 。 挑选你需要的 MySQL Community Server 版本及对应的平台。 注意&#xff1a;安装过程我们需要通过开启管理员权限来安装&#xff0c;否则会由于权限不足导致无法安装。 Linux/UNIX 上安装 MySQL Linux平台上推荐使用RP…

Stable Diffusion Web UI - ControlNet 景深 Depth

Depth 的使用场景为建筑类型带有景深的场景&#xff0c;同样的针对人物也可以&#xff0c;不过 Depth 会限制人物的绘画时的自由发挥范围。 通过 Depth 可以得到类似如下的结果 从上图结果&#xff0c;可以看到&#xff0c;通过 Depth 来控制图片生成&#xff0c;整体图片的结…

UE5 随机生成地牢关卡

参考视频&#xff1a;【UE5 | 教程 | 地编】虚幻引擎5 中创建史诗级 程序化 地下城_哔哩哔哩_bilibili 首先创建一个父项Actor 这个BOX碰撞提是和地板重叠的 这三个是场景组件&#xff0c;这个ExitsFolder下面的箭头等会会在子蓝图中添加 接下来创建BP_MasterRoom的子蓝图&…

计算机网络:网络层 —— 软件定义网络 SDN

文章目录 软件定义网络 SDN远程控制器OpenFlow协议SDN 广义转发流表简单转发负载均衡防火墙 SDN 控制器 软件定义网络 SDN 软件定义网络&#xff08;Software Defined Networking&#xff0c;SDN&#xff09;是一种新兴的网络架构&#xff0c;旨在通过网络控制与数据转发的分离…

软件技术求职简历「优选篇」

【#软件技术简历#】一份精心撰写的简历是增加获得心仪职位的机会。那么&#xff0c;如何才能写出一份既全面又吸引人的软件技术简历呢&#xff1f;以下是幻主简历整理的软件技术简历「优选篇」&#xff0c;欢迎大家阅读收藏&#xff01; 软件技术简历范文&#xff1a; 求职意向…

MQTT实用示例集:Air201版

今天贴出的是Air201版关于MQTT实用示例集&#xff0c;希望大家喜欢。 本示例教你通过使用脚本代码&#xff0c;对Air201模组进行MQTT链接操作。 操作例程包括&#xff1a; MQTT单链接 MQTT多链接 MQTT SSL不带证书链接 MQTT SSL带证书链接 大家可根据自身需求&#xff0c…

ip地址跟路由器有关吗?更换路由器ip地址会变吗

IP地址与路由器之间的关系是一个涉及计算机网络基础知识的话题。在深入探讨这个问题之前&#xff0c;我们首先需要理解IP地址的基本概念以及它在家庭和企业网络中的作用。 IP地址&#xff0c;即互联网协议地址&#xff0c;是分配给网络上的每个设备的数字标签&#xff0c;用于…

CSS综合练习

该综合练习就是为这个静态网页设置CSS样式&#xff0c;使其变成下面的模样 设置CSS样式前&#xff1a; 设置CSS样式后&#xff1a; 其骨架为&#xff1a; <body><div class"qwq"><img src"top.jpg" alt""></div><d…

神经网络基础--什么是神经网络?? 常用激活函数是什么???

前言 本专栏更新神经网络的一些基础知识&#xff1b;案例代码基于pytorch&#xff1b;欢迎收藏 关注&#xff0c; 本人将会持续更新。 神经网络 1、什么是神经网络 人工神经网络&#xff08; Artificial Neural Network&#xff0c; 简写为ANN&#xff09;也简称为神经网络…

《AI大模型对软件开发流程的重塑:变革、优势、挑战与展望》

《AI大模型对软件开发流程的重塑&#xff1a;变革、优势、挑战与展望》 一、传统软件开发流程与模式&#xff08;一&#xff09;传统软件开发流程&#xff08;二&#xff09;传统软件开发模式面临的问题&#xff08;一&#xff09;AI在软件开发中的应用场景&#xff08;二&…

初识C++(上) -- C++的关键字、命名空间、缺省参数以及函数的重载

目录 一、C的关键字&#xff08;C98&#xff09; 二、命名空间 1、命名冲突 2、命名空间 2.1 命名空间的定义 (1). 命名空间定义的例子以及命名空间的嵌套&#xff1a; (2). 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中&#xff1a; 2…

template和span标签的使用

一&#xff1a;template template是模板占位符&#xff0c;可帮助我们包裹元素&#xff0c;而且循环过程当中&#xff0c;template不会被渲染到页面。 <div>ABC</div> <template v-for"(item, index) in 5"><div>{{ index }}</div>&…

Oracle视频基础1.4.4练习

1.4.4 [dbs] 删干净上次创建的bbk ll rm -f *dbf ll rm -f spfilebbk.ora clear ll创建bbk的pfile&#xff0c;准备对应的目录 ll strings spfilewilson.ora | more strings spfilewilson.ora > initbbk.ora :%s/wilson/bbk :%s/*\.//g :wq ll vi initbbk.ora####### 创…

C# 选择导入文件的路径、导出文件的路径

通过C#代码&#xff0c;调出windows风格的文件选择对话框和存储文件对话框。提供界面来选择文件的位置&#xff0c;并将完整路径以字符串形式返回。 1、选择导入文件&#xff0c;获取其路径 C#通过这段代码将弹出一个文件选择对话框&#xff0c;允许用户选择一个文件&#xff…

孤岛的总面积(Dfs C#

卡码网 101题 力扣第 1254. 统计封闭岛屿的数目 也是一样的 差不多是一道题 101. 孤岛的总面积 题目描述 给定一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的矩阵&#xff0c;岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域&…

论文解读 P2《Knowledge Graphs Meet Multi-Modal Learning: A Comprehensive Survey》

论文解读系列文章目录 文章目录 论文解读系列文章目录一、图中公式什么意思&#xff1f;二、“早期的基于匹配和密集嵌入相似性的方法&#xff0c;逐步发展到可学习的检索技术和预训练语言模型&#xff08;PLM&#xff09;生成技术”什么意思&#xff1f;三、在从问题&#xff…

http请求响应详解

http介绍 http协议&#xff1a; Http”协议称为是“超文本传输协议”&#xff08;HTTP-Hypertext transfer protocol&#xff09;。它定义了浏览器怎么向万维网服务器请求万维网文档&#xff0c;以及服务器怎么样把文档传送给浏览器。 https协议&#xff1a; 传统的HTTP协议…

mysql5安全审计

安装插件 插件需要严格与数据库版本适配&#xff0c;不然安装过程中会出现问题 解压插件 cd 插件所在路径unzip audit-plugin-mysql-5.7-1.1.7-921-linux-x86_64.zip#查看mysql默认插件目录 mysql> SHOW GLOBAL VARIABLES LIKE plugin_dir;# 将插件移动到mysql默认插件目…

一文解秘Rust如何与Java互操作

本博客所有文章除特别声明外&#xff0c;均采用CC BY-NC-SA 4.0许可协议。转载请注明来自 唯你 使用场景 JAVA 与 Rust 互操作让 Rust 可以背靠 Java 大生态来做更多事情&#xff0c;而 Java 也可以享受 Rust 语言特性的内存安全&#xff0c;所有权机制&#xff0c;无畏并发。…