东方耀AI技术分享

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 1461|回复: 1
打印 上一主题 下一主题

[C/C++] 多线程共享变量解决2:原子操作atomic

[复制链接]

1365

主题

1856

帖子

1万

积分

管理员

Rank: 10Rank: 10Rank: 10

积分
14450
QQ
跳转到指定楼层
楼主
发表于 2021-8-8 20:41:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式



// 问题抛出:多线程的坑,使用了共享变量
// http://www.ai111.vip/thread-1242-1-1.html
//解决1、三个线程共享了资源,把共享去掉即可 比较高效与简单的方法
//如果可能,必须要用的方法 不使用共享变量就可以了 多定义一下变量即可啊 最后汇总
// 原则:如果没有必要,线程间不要共享资源


//解决2:如果一定要使用共享变量呢?咋办?   从共享变量作文章  原子操作atomic
//std::atomic<int>
//还是会有问题:变量都是原子操作的变量,但是如果多个组合起来又未必是原子操作了!


//多线程共享变量解决2:原子操作atomic



  1. #include <iostream>
  2. //#include <boost/thread/thread.hpp>
  3. #include <thread>
  4. #include <vector>
  5. #include <atomic>



  6. class Counter{
  7. public:
  8.     Counter() : m_count(0) {}
  9.     void addCount() {m_count++;}   //从内存到寄存器 寄存器加1 写回内存
  10.     int count() const {return m_count;}
  11. private:
  12.     //int m_count;
  13.     std::atomic<int> m_count;    //原子操作变量类型  3个操作合并最小单元的原子操作
  14.     // 原子操作的int类型
  15. };

  16. int work(int a){
  17.     //do something
  18.     return a + a;
  19. }


  20. template <typename Iter>
  21. void real_work(Counter& c, double& total_value, Iter b, Iter e){
  22.     for(;b!=e;++b){
  23.         total_value += work(*b);
  24.         c.addCount();
  25.     }
  26. }

  27. bool is_work_finished(Counter& c, int max_times){
  28.     if(c.count() >= max_times){
  29.         std::cout << "work工作已经完成啦!\n" << std::endl;
  30.         return true;
  31.     }
  32.     //std::cout << "work工作_没有完成呢" << std::endl;
  33.     return false;
  34. }



  35. int main(){

  36.     std::cout << "最大并发数=" << std::thread::hardware_concurrency() << std::endl;
  37.     // Counter c1;
  38.     // std::cout << c1.count()<< std::endl;
  39.     // c1.addCount();
  40.     // c1.addCount();
  41.     // std::cout << c1.count()<< std::endl;
  42.     std::vector<int> vec;
  43.     for(int i=0;i<10000000;++i){
  44.         vec.push_back(rand() % 100);
  45.     }
  46.     //没跑一次的时候来计数
  47.     Counter c1;
  48.     double total_value = 0.0f;
  49.     for(auto v : vec){
  50.         total_value += work(v);
  51.         c1.addCount();
  52.     }
  53.     std::cout << "计数器的执行次数=" << c1.count() << "结果=" << total_value << std::endl;

  54.     //开多线程来做同样的工作   三个线程都会去操作的对象:c2和total_value 共享变量
  55.     Counter c2;
  56.     total_value = 0.0f;
  57.     auto iter1 = vec.begin() + (vec.size() / 3);
  58.     auto iter2 = vec.begin() + (vec.size() / 3 * 2);

  59.     //开一个子线程 后台服务  一定要使用共享变量c2
  60.     //问题在这里:线程之间如何保证数据是一致的?
  61.     std::thread service_back([&c2](){
  62.         while (!is_work_finished(c2, 10000000))
  63.         {
  64.             /* 当返回true的时候 该线程才算执行完毕 否则死循环里 */
  65.         }
  66.         
  67.     });
  68.     //一共三个线程  主线程 子线程t1 子线程t2  
  69.     // lambda函数?  知识盲区
  70.     // 引用传进去:c2 total_value
  71.     // 作为值传进去:两个迭代器
  72.     std::thread t1([&c2,&total_value,iter1,iter2](){
  73.         real_work(c2,total_value,iter1,iter2);
  74.     });
  75.     auto end = vec.end();
  76.     std::thread t2([&c2,&total_value,iter2,end](){
  77.         real_work(c2,total_value,iter2,end);
  78.     });


  79.     //主线程里 做第一区间的  
  80.     real_work(c2,total_value,vec.begin(),iter1);

  81.     t1.join();
  82.     t2.join();
  83.     std::cout << "multithread_计数器的执行次数=" << c2.count() << "结果=" << total_value << std::endl;
  84.     service_back.join();
  85.     return 0;
  86. }
复制代码








让天下人人学会人工智能!人工智能的前景一片大好!
回复

使用道具 举报

0

主题

23

帖子

56

积分

注册会员

Rank: 2

积分
56
沙发
发表于 2021-8-13 20:35:32 | 只看该作者
不断充实自己,不断解放自己
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|人工智能工程师的摇篮 ( 湘ICP备2020019608号-1 )

GMT+8, 2024-6-17 23:55 , Processed in 0.182996 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表