【问题标题】:Sharing data generated by one thread with an array of other threads与一组其他线程共享一个线程生成的数据
【发布时间】:2011-01-14 19:21:53
【问题描述】:

有一个线程不时(在无限循环中具有一个函数的线程,函数完成时生成数据)生成一些数据(例如随机整数)。 并且需要不时获取生成的数据的其他 3 个线程(在无限循环中具有一个函数的线程,函数启动时需要数据)。所有这 3 个线程都想在该循环中修改该 int 并返回不同的东西。

如何使第一个线程生成的数据可以被其他线程访问? (抱歉 - 我是 C++ 高手。我可以使用 boost 库。请提供代码和答案。)

【问题讨论】:

  • 你想把消费者(3个线程)生成的数据放在哪里?数据是否应该返回到原来的地方?
  • @AraK:在完美的世界中将它返回到第一个线程(asincronosly),以便它从该数字生成随机 int=)

标签: c++ multithreading boost


【解决方案1】:

这是一个原始示例,演示如何创建一个线程来生成随机数并将它们放入队列中,以及三个消费者线程从队列中提取随机数并在随机数为奇数时打印它们。这个例子有很大的改进空间,为了解释基本设施(thread_group、mutex和随机数生成都使用boost),许多最佳实践没有遵循:

#include <iostream>
#include <queue>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/random.hpp>
#include <boost/bind.hpp>

std::queue<int> random_stream;
boost::mutex random_stream_mutex, output_mutex;
// create a random number generator similar to good ol' std::rand!
boost::mt19937 rand_generator;
boost::uniform_int<> distribution;
auto random_producer = boost::bind(distribution, rand_generator);

bool isodd(int number)
{ return number % 2 == 1; }

void random_generator()
{
    for(;;)
    {
        // generate a random number, then lock the queue and push
        // the number into it.
        int random_number = random_producer();
        random_stream_mutex.lock();
        random_stream.push(random_number);
        random_stream_mutex.unlock();    
    }
}

void output_odd_randoms()
{
    for(;;)
    {
        // lock the queue then extract the number.
        random_stream_mutex.lock();
        int random_number = random_stream.front();
        random_stream.pop();
        random_stream_mutex.unlock();
        // print the extracted number if it is odd!
        if(isodd(random_number))
        {
            output_mutex.lock();
            std::cout << boost::this_thread::get_id() << ": " 
                << random_number << std::endl;
            output_mutex.unlock();
        }
    }
}

int main()
{
    // create the producer and the consumers!
    boost::thread_group threads;
    threads.create_thread(random_generator);
    threads.create_thread(output_odd_randoms);
    threads.create_thread(output_odd_randoms);
    threads.create_thread(output_odd_randoms);
    // wait for ever! :)
    threads.join_all();
}

如您所见,代码使用全局变量,但封装您的数据是一个更好的主意。此外,使用 RAII 锁定机制更优雅,但修改代码以添加它们是微不足道的。

希望对你有帮助,

【讨论】:

  • 这种技术效率极低。为什么人们投票将此作为解决方案?
【解决方案2】:

有很多方法可以做到这一点,具体取决于细节。由于您没有提供太多详细信息,所以让我们使用一些简单且防弹的东西。

  • 创建一个类
  • 添加私有数据成员来存储数据
  • 添加线程安全 get 和 put 方法来读写数据
  • 在全局命名空间中构造您的类
  • 对线程进行编码以根据需要使用 get 和 put 方法

如何使线程安全的 get 和 put 方法?

  • 为您的类添加一个私有互斥锁。
  • 在进入 get 和 put 方法时锁定互斥锁
  • 从 get 和 put 方法退出时解锁互斥锁。

类似这样的:

class mySafeData
{
public:
    void Set( int i ) 
    {
        myMutex.lock();
        myData = i;
        myMutex.unlock();
    }
    void Get( int& i)
    {
        myMutex.lock();
        i = myData;
        myMutex.unlock();
    }
private:
    int myData;
    boost::mutex myMutex;

};

这种方法效率不高。恕我直言,使用最简单和最容易理解的技术让代码工作很重要。一旦运行起来,如果性能有问题,可以优化代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多