C++ 使用 boost::lock_guard 进行简单的共享数据锁定
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3726570/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using boost::lock_guard for simple shared data locking
提问by kfb
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. My example implementation looks like this:
我是 Boost 库的新手,正在尝试实现一个在共享队列上运行的简单生产者和消费者线程。我的示例实现如下所示:
#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 时做错了什么吗?
采纳答案by Steve Townsend
You give your threads (producer & consumer) the mutex
object and then detach them. They are supposed to run forever. Then you exit from your program and the mutex
object is no longer valid. 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.
你给你的线程(生产者和消费者)mutex
对象,然后分离它们。他们应该永远运行。然后退出程序,mutex
对象不再有效。尽管如此,您的线程仍然尝试使用它,他们不知道它不再有效。如果您使用了 NDEBUG 定义,您将获得一个核心转储。
Are you trying to write a daemon application and this is the reason for detaching threads?
您是否正在尝试编写守护程序应用程序,这就是分离线程的原因?
回答by Steve Townsend
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. 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?
这里的消费者模型非常贪婪,不断循环并检查队列上的数据。如果您在数据可用时使用线程间信号而不是这种锁定和窥视循环来确定性地唤醒消费者线程,那么效率会更高(浪费更少的 CPU 周期)。以这种方式思考:当队列为空时,这本质上是一个紧密循环,仅因需要获取锁而中断。不理想?
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
内部工作线程来调解对共享数据的访问。
回答by doron
When main
exits, all the global objects are destroyed. Your threads, however, do continue to run. You therefore end up with problems because the threads are accessing a deleted object.
当main
退出,所有的全局对象被销毁。但是,您的线程会继续运行。因此,您最终会遇到问题,因为线程正在访问已删除的对象。
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. You may want to provide some way of signaling the threads to finish running to save from waiting too long.
底线是您必须在退出之前终止线程。唯一要做的就是让主程序等待(通过使用 a boost::thread::join
)直到线程完成运行。您可能希望提供某种方式来通知线程完成运行以避免等待太长时间。
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
直到有新数据发出信号。