C++ 20 原子引用 (一)
创始人
2024-05-10 02:37:28
0

C++ 20 原子引用 (一)

std::atomic_ref{}

std::atomic_ref类型对其引用的对象进行原子操作。

使用std::atomic_ref 进行多线程读写时不会造成数据争用。被引用对象的生命周期必须超过std::atomic_ref 。操作std::atomic_ref 的子对象是未定义行为。

错误示例

你可能认为在一个原子内使用引用可以实现这种操作,实际上不可以:

#include 
#include 
#include 
#include 
#include struct ExpensiveToCopy
{int counter{};
};int getRandom(int begin, int end)
{std::random_device seed; std::mt19937 engine(seed()); std::uniform_int_distribution<> uniformDist(begin, end);return uniformDist(engine);
}void count(ExpensiveToCopy& exp)
{std::vector v;std::atomic counter{exp.counter}; for (int n = 0; n < 10; ++n){v.emplace_back([&counter]{auto randomNumber = getRandom(100, 200); for (int i = 0; i < randomNumber; ++i) { ++counter; }});}for (auto& t : v) t.join();
}int main()
{std::cout << std::endl;ExpensiveToCopy exp; count(exp);std::cout << "exp.counter: " << exp.counter << '\n';std::cout << std::endl;
}

image.png
最后的结果应该接近1500,所以出现了错误,原因是 std::atomic counter{exp.counter}实际上创建了一个副本。

接下来使用一个简单的示例演示一下:

int main(int argc, char* argv[])
{int val{ 10086 };int& ref = val;std::atomic atomicRef{ ref };++atomicRef;std::cout << std::format("val = {}, ref = {}, atomicRef = {}", val, ref, atomicRef.load()) << std::endl;
}

image.png

使用std::atomic_ref counter{exp.counter}代替std::atomic counter{exp.counter}解决这个问题

#include 
#include 
#include 
#include 
#include struct ExpensiveToCopy
{int counter{};
};int getRandom(int begin, int end)
{std::random_device seed;std::mt19937 engine(seed());std::uniform_int_distribution<> uniformDist(begin, end);return uniformDist(engine);
}void count(ExpensiveToCopy& exp)
{std::vector v;std::atomic_ref counter{exp.counter};for (int n = 0; n < 10; ++n){v.emplace_back([&counter]{auto randomNumber = getRandom(100, 200);for (int i = 0; i < randomNumber; ++i) { ++counter; }});}for (auto& t : v) t.join();
}int main()
{std::cout << std::endl;ExpensiveToCopy exp;count(exp);std::cout << "exp.counter: " << exp.counter << '\n';std::cout << std::endl;
}

看到这里你可能会想为什么不把计数器最开始就定义成原子变量呢像这样:

struct ExpensiveToCopy {
std::atomic counter{};
};

这确实是一个有效的方法,但是对原子变量的操作时同步的,使用std::atomic_ref counter 可以让你显式的控制何时需要对原子变量进行原子访问,因为大多数时间里你可能只需要读取这个变量。

相关内容

热门资讯

安卓系统内存老是爆满,揭秘原因... 手机内存爆满,是不是让你头疼不已?别急,今天就来给你揭秘安卓系统内存老是爆满的奥秘,让你轻松解决这个...
安卓内存转苹果系统,技术解析与... 你有没有想过,手机从安卓系统转到苹果系统,这中间的“搬家”过程,是不是就像我们搬家一样,既兴奋又有点...
安卓系统关闭自动重启,安卓系统... 手机突然重启,是不是让你心头一紧?别急,今天就来教你一招,让你的安卓手机告别自动重启的烦恼!?一、自...
安卓系统卡刷视频,恢复流畅体验 手机用久了是不是感觉有点卡?尤其是安卓系统,有时候刷视频都慢得让人抓狂!别急,今天就来给你支个招,让...
安卓系统占用内存过高,深度剖析... 手机用着用着,是不是感觉内存越来越不够用了?尤其是安卓系统,有时候明明没下载什么大文件,内存却像被无...
安卓系统 耳机 线控,畅享音乐... 你有没有发现,现在手机耳机线控的功能越来越强大了?咱们就来聊聊这个话题,看看安卓系统的耳机线控到底有...
安卓哪个系统续航最好,揭秘哪一... 你有没有想过,为什么你的手机总是没电得那么快?是不是在纠结安卓哪个系统的续航最好呢?别急,今天就来给...
安卓软件转为系统应用,华丽蜕变... 你有没有想过,那些在安卓手机上用得得心应手的软件,竟然可以变成手机系统的一部分呢?没错,就是那种一打...
21pro安卓系统,创新功能与... 你有没有发现,最近你的手机是不是变得聪明多了?没错,说的就是那个让人眼前一亮的21Pro安卓系统!今...
安卓系统扩容硬盘教程,一步到位... 手机里的照片越来越多,游戏也越玩越上瘾,可就是硬盘空间不够用,这可怎么办呢?别急,今天就来教你怎么给...
安卓系统密码解锁软件,高效便捷... 手机解锁成了难题?别急,我来给你支个招! 一、解锁难题,安卓系统密码解锁软件来帮忙生活中,我们总会遇...
安卓系统可能下载吗,探索可能下... 你有没有想过,安卓系统是不是也可以下载呢?这个话题听起来是不是有点意思?毕竟,安卓系统可是智能手机界...
国产电脑板安卓系统,引领智能办... 你有没有想过,家里的电脑板竟然也能用安卓系统?没错,就是那个我们平时手机上用的安卓系统,现在竟然也能...
安卓系统怎么调ins,实际应用... 你有没有发现,Instagram(简称ins)这个社交平台简直是个宝藏,各种美图、短视频,还有各种有...
手机安卓系统耗电好快,揭秘安卓... 亲爱的手机控们,你们是不是也有这样的烦恼:手机安卓系统耗电好快,仿佛电量就像流水一样哗啦啦地溜走?别...
安卓系统能定位软件,探索安卓系... 你有没有想过,你的手机里那些神奇的软件是怎么知道你在哪儿的呢?没错,就是安卓系统能定位软件的功劳!今...
安卓系统参数测试软件,基于安卓... 你有没有想过,你的安卓手机里那些神秘的系统参数,其实就像是一扇通往手机性能深处的窗户呢?想要了解这扇...
透明蓝牙耳机安卓系统,智能生活... 你有没有想过,在这个科技飞速发展的时代,拥有一副好耳机是多么重要的一件事呢?想象当你沉浸在美妙的音乐...
微软10系统安装安卓,跨平台体... 亲爱的读者们,你是否曾想过在Windows 10系统上安装安卓系统呢?想象一边享受着Windows的...
ios跟安卓系统混合,打造跨平... 你有没有发现,现在手机的世界里,iOS和安卓就像是两个截然不同的王国,各自有着忠实的粉丝。但你知道吗...