好吧,我正在尝试处理某种队列。我有一个 IO线程,它专门用于从std :: queue中弹出数据但是问题是我正在使用Sleep()以防止100 %cpu常量检查。 当然还有其他线程会将项添加到std :: queue。
我怎样才能创建事件以便线程处于休眠状态,而当std :: queue非空时,仅会启动?
IO线程
Sleep(100);
while (!myqueue.empty())
{
//process data FIFO
myqueue.pop(); //pop out and continue
}
非常感谢,谢谢!哦,这对于c ++ 11或c ++ 03来说无关紧要 - 在Windows上。
答案 0 :(得分:6)
std::queue
绝对与线程无关。完全没有。它的.empty()
成员不是线程安全的(只是可重入的)!这同样适用于其他所有成员。因此,多个线程可以使用不同的队列,但每次只有一个线程可以对每个实例执行任何操作。
C ++ 11或C ++ 03非常重要。因为C ++ 11定义了线程同步原语,而C ++ 03没有,你必须使用OS API。
在C ++ 11中,您会对std::condition_variable
感兴趣。
在C ++ 03中,您会对Boost.Thread(大部分与C ++ 11兼容)Events或Semaphores感兴趣。
在任何一种情况下,std::queue::push()
和std::queue::pop()
本身都必须受到互斥的保护。 std::condition_variable
甚至会强制您在Windows API中使用std::mutex
来使用Critical Section。
在Windows上,C ++ 11类仅在Visual Studio 2012和Windows 8中可用。较旧的编译器使用Boost(优点是它可以是可移植的)或本机API。
答案 1 :(得分:1)
你需要一个“条件变量”。每当线程在队列上放置某些东西时,它“通知”等待条件变量的线程。消耗队列中事件的线程会等待条件变量。它是睡着的,直到有人通过条件变量通知它。
Boost有一个很好的实现:http://www.boost.org/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref
您正在使用锁来确保对队列的访问是线程安全的,不是吗?
答案 2 :(得分:0)
我的建议是首先研究如何使用线程安全队列,然后考虑使用boost :: condition信令来提供更多控制。
这是一个如何构建线程安全队列的示例:
#pragma once
#include <queue>
template<typename T>
class thread_safe_queue
{
queue<T> m_queue;
pthread_mutex_t m_mutex;
pthread_cond_t m_condv;
public:
thread_safe_queue() {
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_condv, NULL);
}
~thread_safe_queue() {
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_condv);
}
void push(T& item) {
pthread_mutex_lock(&m_mutex);
T itemcpy = std::move(item);
m_queue.push(std::move(itemcpy));
pthread_cond_signal(&m_condv);
pthread_mutex_unlock(&m_mutex);
}
T pop() {
pthread_mutex_lock(&m_mutex);
while (m_queue.size() == 0) {
pthread_cond_wait(&m_condv, &m_mutex);
}
T& _item = m_queue.front();
T itemcpy = std::move(_item);
m_queue.pop();
pthread_mutex_unlock(&m_mutex);
return itemcpy;
}
int size() {
pthread_mutex_lock(&m_mutex);
int size = m_queue.size();
pthread_mutex_unlock(&m_mutex);
return size;
}
};
这是你实例化它的方式:
thread_safe_queue<myclass> myqueue;
如果你想使用事件信令,那么请考虑使用boost :: condition - fx。像这样:
#include <boost/thread/condition.hpp>
#include <boost/thread/mutex.hpp>
boost::mutex mtxWait;
boost::condition cndSignalQueueHasNewEntry;
bool WaitForQueueSignal(long milliseconds)
{
boost::mutex::scoped_lock mtxWaitLock(mtxWait);
boost::posix_time::time_duration wait_duration = boost::posix_time::milliseconds(milliseconds); // http://www.boost.org/doc/libs/1_34_0/doc/html/date_time/posix_time.html
boost::system_time const timeout=boost::get_system_time()+wait_duration; // http://www.justsoftwaresolutions.co.uk/threading/condition-variable-spurious-wakes.html
return cndSignalQueueHasNewEntry.timed_wait(mtxWait,timeout); // wait until signal notify_one or timeout
}
这是您可以发出信号的方式
cndSignalQueueHasNewEntry.notify_one();
这是你可以等待信号的方法
bool bResult = WaitForQueueSignal(10000); // timeout after 10 seconds