【问题标题】:boost conditional not working on thread safe queue with two producers and one consumer提升条件不适用于两个生产者和一个消费者的线程安全队列
【发布时间】:2013-02-12 21:48:07
【问题描述】:

我有两个线程添加到“线程安全”队列中。但是,当第二个线程尝试“推送”内容时。不通知消费者内容可用。队列继续增长,但 notify_one() 从不通知消费方法中的条件。这是为什么呢?

#ifndef CONCURRENT_QUEUE_H
#define CONCURRENT_QUEUE_H

#include <queue>
#include <boost/thread.hpp>

template<typename Data>
class concurrent_queue {
private:
    std::queue<Data> the_queue;
    mutable boost::mutex the_mutex;
    boost::condition_variable the_condition_variable;
public:
    void push(Data const& data) {
        boost::mutex::scoped_lock lock(the_mutex);
        the_queue.push(data);
        lock.unlock();
        the_condition_variable.notify_one();
    }

    void wait_and_pop(Data& popped_value) {
        boost::mutex::scoped_lock lock(the_mutex);
        while(the_queue.empty()) {
            the_condition_variable.wait(lock);
        }

        popped_value=the_queue.front();
        the_queue.pop();
    }
};
#endif

此代码在 Fedora 14 中使用 boost 1.51.0 有效,但在 windows 7 中的 boost 1.50.0 中无效。

INCLUDEPATH += \
    . \
    /home/mehoggan/Devel/x86-fps/boost_1_50_0/include

LDFLAGS += -Wl,-rpath=/home/mehoggan/Devel/x86-fps/boost_1_50_0/lib

LIBS += \
    -L/home/mehoggan/Devel/x86-fps/boost_1_50_0/lib \
    -lboost_system \
    -lboost_thread \
    -lz

#ifndef CONCURRENT_QUEUE_H
#define CONCURRENT_QUEUE_H

#include <queue>
#include <boost/thread.hpp> // Using boost 1.50.0

template<typename Data>
class concurrent_queue {
private:
    std::queue<Data> the_queue;
    mutable boost::mutex the_mutex;
    boost::condition_variable the_condition_variable;
public:
    void push(Data const& data) {
        boost::mutex::scoped_lock lock(the_mutex);
        the_queue.push(data);
        lock.unlock();
        the_condition_variable.notify_all();
    }

    void wait_and_pop(Data& popped_value) {
        boost::mutex::scoped_lock lock(the_mutex);
        while(the_queue.empty()) {
            the_condition_variable.wait(lock);
        }

        popped_value=the_queue.front();
        the_queue.pop();
    }
};
#endif

concurrent_queue<int> the_queue;

void thread1func() {
    do {
        the_queue.push(1);
    } while (true);
}

void thread2func() {
    do {
        the_queue.push(2);
    } while (true);
}

void thread3func() {
    do {
        int read;
        the_queue.wait_and_pop(read);

        std::cout << "I read from thread " << read << std::endl;
    } while (true);
}

int main(int argc, char *argv[]) {
    boost::thread thread1 = boost::thread(thread1func);
    boost::thread thread2 = boost::thread(thread2func);
    boost::thread thread3 = boost::thread(thread3func);

    thread1.join();
    thread2.join();
    thread3.join();
}

【问题讨论】:

  • 您能否提供一个小驱动程序main() 来说明问题?我假设消费者正在调用wait*pop() 函数之一?
  • 当然是一秒。致力于将代码整合在一起。
  • 虽然编辑的代码很有用,但sscce,有int main() 并且可以轻松编译的东西会更好
  • 我还尝试了基于 Boost 1.49 库构建的 VS 2010 程序,并且消费者线程保持阻塞没有问题 - 它继续读取从线程 1 和 2 发布的数据。
  • @megabyte1024:你说得对,unlock() 不是必需的,但也不是不正确的。在通知条件变量之前释放锁是为了防止等待线程被通知解除阻塞而立即被通知线程不必要地仍然持有的互斥锁阻塞的情况。

标签: c++ boost concurrency queue


【解决方案1】:

您的 Makefile 似乎没有使用 -pthread/-mthreads。一般来说,如果您不要求编译器生成多线程代码,则根本不要期望您的代码可以工作。

【讨论】:

    猜你喜欢
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 2013-09-30
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 2023-03-23
    相关资源
    最近更新 更多