【问题标题】:Why does add function have no effect in c++ 11 thread?为什么add函数在c++ 11线程中没有效果?
【发布时间】:2016-10-26 14:45:00
【问题描述】:

我正在尝试学习 c++ 11 线程并有以下代码:

#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <algorithm>

void add(int&  i){
    std::mutex some_mutex;
   // std::cout << " I am " << std::endl;
    std::lock_guard<std::mutex> guard(some_mutex); 
    i++;
}


int main(){
    int i = 0;
    std::vector<std::thread> vec_threads;

    for(int i = 0; i < 10; i++){
        vec_threads.push_back(std::thread(add,std::ref(i)));
    }

    std::for_each(vec_threads.begin(),vec_threads.end(),
            std::mem_fn(&std::thread::join));
    std::cout<< " i = " << i << std::endl;
return 0;
}

我创建了一个包含std::threadvector,我从每个线程调用add 函数并通过引用传递i。在我假设线程会做的事情(添加i = i+1)之后,最终结果并没有反映我想要的。


输出:i = 0

预期输出:i = 10

【问题讨论】:

  • @Ajay 但 user1887915 也对我为每个线程创建的互斥锁持正确态度......这是个糟糕的主意。

标签: c++ multithreading c++11 output stdthread


【解决方案1】:

Mutex 需要在线程之间共享才能得到正确的结果。并且i被循环变量遮蔽,将其替换为j

#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <algorithm>

void add(int&  i, std::mutex &some_mutex){
   // std::cout << " I am " << std::endl;
    std::lock_guard<std::mutex> guard(some_mutex); 
    i++;
}


int main(){
    int i = 0;
    std::vector<std::thread> vec_threads;
    std::mutex some_mutex;

    for(int j = 0; j < 10; j++){
        vec_threads.push_back(std::thread(add,std::ref(i), std::ref(some_mutex)));
    }

    std::for_each(vec_threads.begin(),vec_threads.end(),
            std::mem_fn(&std::thread::join));
    std::cout<< " i = " << i << std::endl;
    return 0;
}

【讨论】:

  • @pokche,除了通过其他变量取消隐藏i 之外,您还可以在原始代码中将some_mutex 设置为static。对我来说,这似乎比每次都传递std::mutex 更可行。
  • @iammilind:IMO 这是一个糟糕的设计。它使您可以方便地做一件事,但其他任何事情的性能都会很差或不可能(例如,不同的线程组使用不同的int 对象,或者调用需要同步的addsub 的线程)。
  • @Hurkyl,当我们处理不同的int i 变量时,您的论点是正确的。但是,我相信上面只是一个玩具代码。因为在实时中,不同int is 的不同线程组也会有不同的功能。此外,对于这种特定情况,int i 本身将作为static 变量封装在add()(或某个类)中。在方法中包含static mutex 是一种常见的设计模式。
  • @pokche:因为它允许一个且恰好一个同步模型。如果那是您想要的模型,那就太好了。但是,如果线程正在处理独立的数据并且不需要同步......你无论如何都强制它们同步。如果您希望对 addsub 的调用进行同步...您无法使用现有的互斥体,因此您必须在其之上添加一个额外的外部同步层。
  • @pokche:global-embedded-in-the-function 如果它实际上是在保护一个真正的全局资源免受并发访问(并且如果该函数是该资源的唯一访问点),那么它是有意义的。但是在其他情况下使用它(例如保护对用户提供的函数参数的访问)是不必要的限制。
猜你喜欢
  • 2013-11-14
  • 2012-07-22
  • 2011-10-10
  • 2013-02-12
  • 2014-10-26
  • 1970-01-01
  • 2017-09-12
  • 1970-01-01
相关资源
最近更新 更多