[C/C++11]_[WTL/ATL]_[多线程如何无锁更新进度条界面上的描述字符串]

场景

  1. 开发界面程序WTL/Win32时,经常会使用进度条来实时显示百分比和描述文字。这些文字一般都用一个成员变量wstring来存储,而文字的更新可能比较频繁,比如下载复制文件时,显示正在复制的文件名。可能500ms就需要更新一次文字。 绘制是在主线程操作,那么更新和读取得常见做法是工作线程发送消息到需要更新的文本到主线程,之后主线程取出消息并更新文本。这么做的缺陷就是需要发送的消息太多了。有没有更好的办法?

说明

  1. 如果是多线程更新变量,那么只有两种做法,一个是加互斥量(加锁)更新,一个是无锁更新。

    • 加锁更新的缺点很明显,在读写的时候都需要加锁,大概率会导致主线程卡顿,肯定的是CPU资源是损耗很多的。
    • 另外一个就是无锁更新,在工作线程直接调用无锁更新变量的方法。 无锁更新一个变量在C++11里提供了atomic_loadatomic_store的方法。
  2. atomic_loadatomic_store都需要参数shared_ptr<T>来操作,本质上是对指针进行操作。也就是可以对shared_ptr<wstring>变量类型操作。

  3. atomic_loadatomic_store也可以使用volatile数值类型或者atomic<T>类型,而T如果对象类型只支持扁平对象,如果是atomic<string>编译会报错

error C2338: atomic<T> requires T to be trivially copyable.
  1. atomic_load是原子复制一个shared_ptr<T>并返回,我们多线程操作计数+1的共享指针并没有问题,即使旧的shared_ptr<T>销毁。 它复制shared_ptr<T>是原子的,这里说明一个问题,多线程修改shared_ptr<T>共享变量并不是原子的,即对shared_ptr的计数+1-1。 注意,不能再使用=来进行复制共享指针。

  2. volatile变量更新不是原子的,有可能多线程在某一个时刻修改这个变量导致值丢失。可以看例子的add变量之所以用atomic<int64>而不是volatile int64_t就是因为这个原因。

string get() {auto one = atomic_load(&desc_);return (one) ? *one.get() : "";
}
  1. 对应修改的方法是atomic_store原子修改一个shared_ptr共享指针的实际对象。注意,不能再使用=来进行复制共享指针。
void update(const char* desc) {auto now = make_shared<string>("world");atomic_store(&desc_, now);
}

例子

// test-atomic-modify-string.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <atomic>
#include <thread>
#include <string>
#include <memory>using namespace std;struct Si
{int i;int i1;int i2;
};class Dialog
{
public:Dialog() {desc_ = make_shared<string>("hello");}string get() {auto one = atomic_load(&desc_);return (one) ? *one.get() : "";}void update(const char* desc) {auto now = make_shared<string>("world");atomic_store(&desc_, now);}private:shared_ptr<string> desc_;};static const int gTextThreadNum = 10;void TestAtomicModifyPointerString()
{// 编译错误: error C2338: atomic<T> requires T to be trivially copyable.// atomic的特化类型必须是扁平结构, 比如C结构体// atomic<string> str;// 需要sizeof()大于8// atomic<Si> ssi;// volatile : 写不是原子的Dialog dialog;std::thread threads[gTextThreadNum];atomic<int64_t> add(0);auto func = [&add](Dialog* dialog) {for (auto i = 0; i < 10000; ++i) {auto temp = dialog->get();if (temp.size())add.fetch_add(1);dialog->update((i % 2)?"hello":"world");}};cout << "---- synchronized ----" << endl;for (auto i = 0; i < gTextThreadNum; ++i)threads[i] = move(std::thread(func,&dialog));for (auto i = 0; i < gTextThreadNum; ++i)threads[i].join();cout << dialog.get() << " -> " << add.load() << endl;
}int main()
{std::cout << "Hello World!\n";TestAtomicModifyPointerString();
}

输出

Hello World!
---- synchronized ----
world -> 100000

参考

  1. std::atomic_load

  2. std::atomic_store

  3. std::shared_ptr

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

H5双人五子棋小游戏

H5小游戏源码、JS开发网页小游戏开源源码大合集。无需运行环境,解压后浏览器直接打开。有需要的,私信本人,发演示地址,可以后再订阅,发源码,含60+小游戏源码。如五子棋、象棋、植物大战僵尸、开心消消乐、扑鱼达人、飞机大战等等 <!DOCTYPE html> <html> <…

移动开发:网格视图

一、在新建GridView模块下添加图片以及创建cell.xml文件 1.粘贴图片时选择红框中的路径&#xff0c;点击“OK” 2.在路径后添加-mdpi后缀,再点击“OK” 二、相关代码块 1.MainActivity.java文件代码 package com.example.gridview;import androidx.appcompat.app.AppCompatAc…

备考2024年北京高考数学:20114~2023十年选择题练习和解析

距离2024年高考还有三个月的时间&#xff0c;如何用三个月的时间再提高北京数学高考的成绩&#xff1f;吃透历年真题以及背后的知识点是行之有效的方法 之一。 今天我们来看一下2014-2023年的北京市高考数学的选择题&#xff0c;从过去十年&#xff08;2014-2023&#xff09;的…

面试问答总结之并发编程

文章目录 &#x1f412;个人主页&#xff1a;信计2102罗铠威&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;多线程的优点、缺点&#x1f415;并发编程的核心问题 &#xff1a;不可见性、乱序性、非原子性&#x1fa80;不可见性&#x1fa80;乱序性&am…

【真机Bug】异步加载资源未完成访问单例导致资源创建失败

1.错误表现描述 抽卡时&#xff0c;10抽展示界面为A。抽取内容可能是整卡或者碎片&#xff0c;抽到整卡&#xff0c;会有立绘展示和点击详情的按钮。点击详情后出现详情页B。【此时界面A预制体被销毁&#xff0c;卡片数据进入数据缓存池】点击页面B的返回按钮&#xff0c;单例…

刚刚,OpenAI官方发文驳斥马斯克,自曝8年间邮件往来截图

文章开篇表示&#xff1a;「OpenAI 的使命是确保 AGI 惠及全人类&#xff0c;这意味着既要构建安全、有益的 AGI&#xff0c;又要帮助创造广泛的利益。我们正在分享我们在实现使命方面所学到的知识&#xff0c;以及有关我们与马斯克关系的一些事实。我们打算驳回马斯克的所有主…

回归啦!!!

消失的日子在实习&#xff0c;今天最后一天了来看看自己的学习日志&#xff0c;有没有可以和小伙伴交流的部分吧&#xff01; 目录 一、产品one ①简介 ②底层原理 ③知识点一 作用一&#xff1a;日志采集 作用二&#xff1a;实时监测 作用三&#xff1a;规则匹配 作用…

Word中Endnote加载项不见了怎么处理?

打开word-①文件-②选项-③加载项 勾选endnote cite while you write 完成上述操作后&#xff0c;endnote便出现在菜单栏中。

[C语言]——分支和循环(2)

目录 一.逻辑操作符&#xff1a;&& , || , &#xff01; 1.逻辑取反运算符! 2.与运算符&& 3.或运算符 4.练习&#xff1a;闰年的判断 5.短路 二.switch语句 1.if语句和switch语句的对比 2.switch语句中的break 3.switch语句中的default 4.switch…

【C++】类的默认成员函数(上)

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、默认成员函数二、构造函数构造函数的概念及特性 三、析构函数析构函数的特性…

论文笔记:Compact Multi-Party Confidential Transactions

https://link.springer.com/chapter/10.1007/978-3-030-65411-5_21 A compact, private, Multi-Party Confidential Transactions (MCT) 紧凑型多方机密交易&#xff08;Compact MCT&#xff09;&#xff1a;MCT的长度与常规的单一所有者交易一样短&#xff1b;换句话说&…

【大数据架构(3)】Lambda vs. Kappa Architecture-选择你需要的架构

文章目录 一. Data Processing Architectures1. Lambda Architecture1.1. 架构说明a. Data Ingestion Layerb. Batch Layer (Batch processing)c. Speed Layer (Real-Time Data Processing)d. Serving Layer 1.2. Lambda Architecture的优缺点1.3. 使用案例 2. Kappa Architect…

MongoDB Helloworld For Window

1. 下载MongoDB Download MongoDB Community Server | MongoDB 2. 安装MongoDB 3. 创建DB. 4. 用java code 连接mongo. 做增删改查操作。 pom.xml <dependency><groupId>org.mongodb</groupId><artifactId>mongodb-driver-sync</artifactId>&…

docker 基础(二)

常见命令 Docker最常见的命令就是操作镜像、容器的命令&#xff0c;详见官方文档&#xff1a;https://docs.docker.com/ 数据卷 命令说明文档地址docker volume create创建数据卷docker volume createdocker volume ls查看所有数据卷docker volume lsdocker volume rm删除数…

0.8秒一张图40hx矿卡stable diffusion webui 高质极速出图组合(24.3.3)

新消息是。经过三个月的等待&#xff0c;SD Webui (automatic1111)终于推出了新版本1.8.0&#xff0c;本次版本最大的更新&#xff0c;可能就是pytorch更新到2.1.2, 不过还是晚了pytorch 2.2.2版。 不过这版的一些更新&#xff0c;在forget分支上早就实现了&#xff0c;所以。…

C及C++每日练习(2)

1.选择&#xff1a; 1.使用printf函数打印一个double类型的数据&#xff0c;要求&#xff1a;输出为10进制&#xff0c;输出左对齐30个字符&#xff0c;4位精度。以下哪个选项是正确的&#xff1f; A.%-30.4e B.%4.30e C.%-30.4f D.%-4.30 在上一篇文章中&#xff0c;提到了…

【C++实战项目】Date日期类 --- 运算符重载的深入探索

&#x1f4f7; 江池俊&#xff1a;个人主页 &#x1f525; 个人专栏&#xff1a;✅C那些事儿 ✅Linux技术宝典 &#x1f305; 此去关山万里&#xff0c;定不负云起之望 文章目录 引言一、为什么需要运算符重载&#xff1f;二、日期类的实现1. 基本框架2. 预备工作3. Date 类…

Linux Watchdog 机制是什么

当涉及到Linux操作系统的稳定性和可靠性时&#xff0c;Linux Watchdog机制是一个至关重要的议题。该机制旨在监控系统状态&#xff0c;确保在出现问题时采取适当的措施以维持系统的正常运行。本文将深入探讨Linux Watchdog机制的工作原理、应用范围以及如何配置和使用该机制来提…

【leetcode C++】电话号码的字母组合

17. 电话号码的字母组合 题目 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 题目链接 . - 力扣&#xff08;LeetCode&…

MyBatis 学习(六)之动态 SQL

目录 1 动态 SQL 介绍 2 if 标签 3 where 标签 4 set 标签 5 trim 标签 6 choose、when、otherwise 标签 7 foreach 标签 8 bind 标签 1 动态 SQL 介绍 动态 SQL 是 MyBatis 强大特性之一&#xff0c;极大的简化我们拼装 SQL 的操作。MyBatis 的动态 SQL 是基于 OGNL 的…