【问题标题】:Receiving results from a thread从线程接收结果
【发布时间】:2018-12-24 16:21:45
【问题描述】:

我正在使用以下代码创建 10 个线程。我希望从我的线程中收到不同的随机数并打印出来。但结果是一样的。

#include "pch.h"
#include <iostream>
#include "C.h"
#include "BB.h"
#include <vector>
#include <thread>
#include <mutex>
#include <future>

void initiazer(std::promise<int> * promObj, int i)
{

    std::cout << "Inside Thread " <<i<< std::endl;     
    (promObj)->set_value((rand() % 100) + 1);
}

int main()
{
    srand((unsigned)time(0));
    std::promise<int> promiseObj[10];
    std::future<int> futureObj [10];
    std::thread th[10];
    for (size_t i = 0; i < 10; i++)
    {       
        futureObj[i] = promiseObj[i].get_future();
    }

    for (size_t i = 0; i < 10; i++)
    {
        th[i] = std::thread(initiazer,&promiseObj[i],i) ;
        std::cout << futureObj[i].get() << std::endl;       
    }

    for (size_t i = 0; i < 10; i++)
    {
        th[i].join();
    }
    return 0;
}

【问题讨论】:

  • futureObj[i].get() 将阻塞,直到您刚刚启动的线程完成。

标签: c++ multithreading stdthread


【解决方案1】:

rand() 不是线程安全的,请参阅https://linux.die.net/man/3/rand。请改用random 中定义的更现代的函数,例如

std::random_device rd;
auto seed = rd ();
std::mt19937 mt (seed);
....
auto random_number = mt ();

编辑:

正如其他人指出的那样,mt19937::operator () 也不能保证是线程安全的。最好按照 n.m. 的建议,为每个线程创建其中一个对象,如更新的现场演示现在所示。

Live demo

【讨论】:

  • @PeteBecker std::mt19937 是一种类型。为什么它不是线程安全的,这意味着什么?
  • @PeteBecker 在这种情况下,我猜它必须由互斥锁保护(或仅在单个线程上调用)。
  • @PaulSanders 我很确定每个线程有一个单独的std::mt19937 对象就足够了。当然,需要对每一个进行不同的播种以获得不同的值(默认的 random_device 通常会起作用)。
  • @PaulSanders -- 互斥锁或单线程也适用于rand()。正如另一条评论所示,有一个更好的答案。但是当人们在不了解他们能做什么和不能做什么的情况下推荐“更现代的功能”时,我会真的很生气。膝跳反应不是正确的设计。
  • @PeteBecker 这不是下意识的反应。在建议使用这些函数之前,我会检查 cppreference 的竞争条件,但没有指定任何函数,但我更喜欢 n.m 的想法,因为它可以保证工作并相应地更新了我的答案。
猜你喜欢
  • 2012-06-09
  • 1970-01-01
  • 2022-01-04
  • 2023-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多