C++并发编程实战 #2 在线程间共享数据

2024-06-10 13:04

本文主要是介绍C++并发编程实战 #2 在线程间共享数据,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

用互斥保护数据

在C++中,通过构造mutex的实例来创建互斥,调用成员函数lock()对其进行加锁,调用unlock()进行解锁。

不推荐直接使用成员函数进行加锁和解锁,因为若按此处理,则在函数的每条代码路径上都要调用unlock(),包括由于异常导致退出的路径。

因此,使用lock_guard<>来进行加锁和解锁。其在构造时给互斥加锁,在析构时解锁,从而保证互斥总被正确解锁。

int a = 0;
mutex m;void func() {lock_guard<mutex> guard(m);for (int i = 0; i < 10000; i++)a++;
}void otherfunc() {lock_guard<mutex> guard(m);for (int i = 0; i < 10000; i++)a++;
}int main()
{cout << a << endl;thread t1(func);thread t2(otherfunc);t1.join();t2.join();cout << a << endl;return 0;
}

指针或引用会造成互斥保护失效

class some_data{int a;string b;
public:void do_sth();
};class data_wrapper{some_data data;mutex m;
public:template<typename Function>void process_data(Function func){lock_guard<mutex> l(m);func(data);}
};some_data* unprotected;void malicious_function(some_data& protected_data){unprotected = &protected_data;
}data_wrapper x;void foo(){x.process_data(malicious_function);unprotected->do_sth();
}

在上面的例子中,process_data()函数内用lock_guard保护了数据的共享。但是,其参数是使用者提供的函数。

在foo()中,传入malicious_function,绕过了保护,直接调用了do_sth。

对于这种问题,C++线程库没有处理的方法,只有靠开发者正确的锁定互斥。

不得向锁所在的作用域之外传递指针和引用,指向受保护的数据。无论是通过函数返回值将它们保存到对外可见的内存,还是将它们作为参数传递给使用者提供的函数。

接口固有的条件竞争

在涉及到接口的情况下,有可能遇到条件竞争。如果多线程对同一个栈数据结构使用互斥进行数据读写操作,在线程调用empty()或size()时,返回值可能是正确的,但是一旦函数返回,其他线程不再受限,那么就能自由的访问栈容器,可能会有其他数据出栈或入栈,令前面的线程得到的结果失效。

stack<int> s;
if(!s.empty()){int value = s.top();s.pop();do_sth(value);
}

在empty与top()中间,可能会有其他线程调用pop()。这是典型的条件竞争,根本原因在于函数接口,即使在内部使用互斥保护栈容器中的元素,也无法防范。

需要将接口函数定义为线程安全的,例如重写一个线程安全的threadsafe_stack类。

这篇关于C++并发编程实战 #2 在线程间共享数据的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1048233

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置