我正在使用the following的阻塞队列实现,但是在尝试从两个不同的线程访问push()
时遇到了死锁。我来自Java背景,因此我对C ++线程的经验有限。
我没有Boost,并且想坚持使用STL,所以我用他们的STL同行修改了boost引用。
template<typename D>
class blocking_queue {
private:
std::queue<D> queue;
mutable std::mutex queue_mutex;
const size_t queue_limit;
bool is_closed = false;
std::condition_variable new_item_or_closed_event;
std::condition_variable item_removed_event;
#ifndef NDEBUG
size_t pushes_in_progress = 0;
#endif
public:
blocking_queue(size_t size_limit = 0) : queue_limit(size_limit) {}
void push(const D& data) {
std::lock_guard lock(queue_mutex);
#ifndef NDEBUG
++pushes_in_progress;
#endif
if (queue_limit > 0) {
while (queue.size() >= queue_limit) {
item_removed_event.wait(lock);
}
}
assert(!is_closed);
queue.push(data);
#ifndef NDEBUG
--pushes_in_progress;
#endif
lock.unlock();
new_item_or_closed_event.notify_one();
}
bool try_push(const D& data) {
std::unique_lock lock(queue_mutex);
if (queue_limit > 0) {
if (queue.size() >= queue_limit) {
return false;
}
}
assert(!is_closed);
queue.push(data);
lock.unlock();
new_item_or_closed_event.notify_one();
return true;
}
void close() {
std::unique_lock lock(queue_mutex);
assert(!is_closed);
#ifndef NDEBUG
assert(pushes_in_progress == 0);
#endif
is_closed = true;
lock.unlock();
new_item_or_closed_event.notify_all();
}
D front() {
if (queue.empty()) {
return {};
}
return queue.front();
}
bool pop(D & popped_value) {
std::unique_lock lock(queue_mutex);
while (queue.empty()) {
if (is_closed) {
return false;
}
new_item_or_closed_event.wait(lock);
}
popped_value = queue.front();
queue.pop();
item_removed_event.notify_one();
return true;
}
bool try_pop(D & popped_value) {
std::unique_lock lock(queue_mutex);
if (queue.empty()) {
return false;
}
popped_value = queue.front();
queue.pop();
item_removed_event.notify_one();
return true;
}
bool empty() const {
std::unique_lock lock(queue_mutex);
return queue.empty();
}
bool closed() const {
std::unique_lock lock(queue_mutex);
return is_closed;
}
size_t limit() const {
return queue_limit;
}
size_t size() const
{
std::unique_lock lock(queue_mutex);
return queue.size();
}
};
为两个不同的线程重用同一个互斥锁是我的问题吗?我对CPU如何知道哪些线程需要首先发出信号感到困惑。