悉野小楼

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

C++多线程不加锁操作同一个整数

复制代码
#include <iostream>
#include <thread>
#include <vector>
#include <chrono>
#include <atomic>
using namespace std;

int num = 0;
//volatile int num = 0;
//atomic<int> num = 0;
void add()
{
    int times = 0;
    for (int i = 0; i < 10000; ++i)
    {
        //std::cout << std::this_thread::get_id() << ":" << num++ << std::endl;
        num++;
        this_thread::sleep_for(chrono::milliseconds(0));
        times++;
    }
    std::cout << "thread id: [" << std::this_thread::get_id() << "] run times:" << times << std::endl;
}
int main()
{
    vector<thread> vects;
    for (int i = 0; i < 2; ++i)
    {
        vects.push_back(thread(add));
    }
    for (auto& t : vects)
    {
        t.join();
    }
    std::cout << "main thread, final num: " << num << std::endl;
}
复制代码

上面是两线程同时对num执行自加操作, 实际输出结果:

thread id: [29524] run times:10000
thread id: [30444] run times:10000
main thread, final num: 17766

两个进程每个线程执行对同一个数连加10000次,  加锁或使用atomic的值应该是20000. 

网上有说单个数值可以不用加锁的原因是, 单条cpu指令取这个整数值是不会出错的. 他们推荐类对象或struct要加锁, 比如struct strTest{int a, int b}, 取strTest数据, 需要两条指令才能完成, 先取a值, 再取b值, 多线程时会有其它指令在中间正好修改了b值.

volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。volatile 提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。

posted on   悉野  阅读(135)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示