简体   繁体   English

使用boost :: lock_guard进行简单的共享数据锁定

[英]Using boost::lock_guard for simple shared data locking

I am a newcomer to the Boost library, and am trying to implement a simple producer and consumer threads that operate on a shared queue. 我是Boost库的新手,我正在尝试实现一个在共享队列上运行的简单生产者和消费者线程。 My example implementation looks like this: 我的示例实现如下所示:

#include <iostream>
#include <deque>
#include <boost/thread.hpp>

boost::mutex mutex;
std::deque<std::string> queue;

void producer() 
{
    while (true) {
        boost::lock_guard<boost::mutex> lock(mutex);

        std::cout << "producer() pushing string onto queue" << std::endl;

        queue.push_back(std::string("test"));
    }
}

void consumer()
{
    while (true) {
        boost::lock_guard<boost::mutex> lock(mutex);

        if (!queue.empty()) {
            std::cout << "consumer() popped string " << queue.front() << " from queue" << std::endl;

            queue.pop_front();
        }
    }
}

int main()
{
    boost::thread producer_thread(producer);
    boost::thread consumer_thread(consumer);

    sleep(5);

    producer_thread.detach();
    consumer_thread.detach();

    return 0;
}

This code runs as I expect, but when main exits, I get 这段代码按照我的预期运行,但是当main退出时,我得到了

/usr/include/boost/thread/pthread/mutex.hpp:45:    
    boost::mutex::~mutex(): Assertion `!pthread_mutex_destroy(&m)' failed.
consumer() popped string test from queue
Aborted

(I'm not sure if the output from consumer is relevant in that position, but I've left it in.) (我不确定consumer的输出是否与该位置相关,但我已将其保留。)

Am I doing something wrong in my usage of Boost? 我在使用Boost时做错了什么?

A bit off-topic but relevant imo (...waits for flames in comments). 有点偏离主题但相关的imo(...等待评论中的火焰)。

The consumer model here is very greedy, looping and checking for data on the queue continually. 这里的消费者模型非常贪婪,不断循环和检查队列中的数据。 It will be more efficient (waste less CPU cycles) if you have your consumer threads awakened determistically when data is available, using inter-thread signalling rather than this lock-and-peek loop. 如果您的消费者线程在数据可用时确定性地唤醒,使用线程间信令而不是此锁定循环,那么它将更有效(浪费更少的CPU周期)。 Think about it this way: while the queue is empty, this is essentially a tight loop only broken by the need to acquire the lock. 以这种方式思考:当队列为空时,这实际上是一个紧密的循环,只是因为需要获取锁。 Not ideal? 不理想?

void consumer()
{
    while (true) {
        boost::lock_guard<boost::mutex> lock(mutex);

        if (!queue.empty()) {
            std::cout << "consumer() popped string " << queue.front() << " from queue" << std::endl;

            queue.pop_front();
        }
    }
}

I understand that you are learning but I would not advise use of this in 'real' code. 我知道你正在学习,但我不建议在“真正的”代码中使用它。 For learning the library though, it's fine. 虽然学习图书馆,但没关系。 To your credit, this is a more complex example than necessary to understand how to use the lock_guard, so you are aiming high! 值得赞扬的是,这是一个比理解如何使用lock_guard所必需的更复杂的例子,所以你的目标很高!

Eventually you will most likely build (or better if available, reuse) code for a queue that signals workers when they are required to do work, and you will then use the lock_guard inside your worker threads to mediate accesses to shared data. 最终,您很可能构建(或更好,如果可用,重用)代码,以便在需要工作时向工作者发出信号,然后您将使用工作线程内的lock_guard来调解对共享数据的访问。

You give your threads (producer & consumer) the mutex object and then detach them. 您为线程(生产者和消费者)提供mutex对象,然后将它们分离。 They are supposed to run forever. 他们应该永远奔跑。 Then you exit from your program and the mutex object is no longer valid. 然后退出程序并且mutex对象不再有效。 Nevertheless your threads still try to use it, they don't know that it is no longer valid. 然而你的线程仍然试图使用它,他们不知道它不再有效。 If you had used the NDEBUG define you would have got a coredump. 如果您使用过NDEBUG定义,那么您将获得一个coredump。

Are you trying to write a daemon application and this is the reason for detaching threads? 您是否正在尝试编写守护程序应用程序,这是分离线程的原因?

When main exits, all the global objects are destroyed. main退出时,所有全局对象都被销毁。 Your threads, however, do continue to run. 但是,您的线程会继续运行。 You therefore end up with problems because the threads are accessing a deleted object. 因此,您最终会遇到问题,因为线程正在访问已删除的对象。

Bottom line is that you must terminate the threads before exiting. 底线是你必须在退出之前终止线程。 The only what to do this though is to get the main program to wait (by using a boost::thread::join ) until the threads have finished running. 唯一要做的就是让主程序等待(通过使用boost::thread::join ),直到线程完成运行。 You may want to provide some way of signaling the threads to finish running to save from waiting too long. 您可能希望提供某种方式来通知线程完成运行以节省等待太长时间。

The other issue is that your consumer thread continues to run even when there is not data. 另一个问题是,即使没有数据,您的消费者线程也会继续运行。 You might want to wait on a boost::condition_variable until signaled that there is new data. 您可能希望等待boost::condition_variable直到发出新数据的信号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM