创建阻止队列 [英] Creating a Blocking Queue

查看:121
本文介绍了创建阻止队列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时, BlockingQueue 的实现和执行只是工作。有时它segfaults。任何想法为什么?

  #include< thread> 
using std :: thread;
#include< mutex>
using std :: mutex;
#include< iostream>
using std :: cout;
using std :: endl;
#include< que>
using std :: queue;
#include< string>
using std :: string;
using std :: to_string;
#include< functional>
using std :: ref;

template< typename T>
class BlockingQueue {
private:
mutex mutex_;
queue< T>队列_;
public:
T pop(){
this-> mutex_.lock();
T value = this-> queue_.front();
this-> queue_.pop();
this-> mutex_.unlock();
返回值;
}

void push(T value){
this-> mutex_.lock();
this-> queue_.push(value);
this-> mutex_.unlock();
}

bool empty(){
this-> mutex_.lock();
bool check = this-> queue_.empty();
this-> mutex_.unlock();
return check;
}
};

void fillWorkQueue(BlockingQueue< string>& workQueue){
int size = 40000;
for(int i = 0; i workQueue.push(to_string(i));
}

void doWork(BlockingQueue< string>& workQueue){
while(!workQueue.empty()){
workQueue.pop
}
}

void multiThreaded(){
BlockingQueue< string> workQueue;
fillWorkQueue(workQueue);
thread t1(doWork,ref(workQueue));
thread t2(doWork,ref(workQueue));
t1.join();
t2.join();
cout<< done\\\
;
}

int main(){
cout<< endl;

//多线程
cout< multiThreaded \\\
;
multiThreaded();
cout<< endl;
}


解决方案

>

如果你调用 .front()



code>在一个空容器上,最好先检查 .empty()



尝试:

  T pop(){
this-> mutex_.lock();
T value;
if(!this-> queue_.empty())
{
value = this-> queue_.front(); //未定义的行为如果queue_为空
//可能会segfault,可能抛出等
this-> queue_.pop();
}
this-> mutex_.unlock();
返回值;
}



注意:由于原子操作对这种队列很重要,推荐API更改:

  bool pop(T& t); //如果没有可读的则返回false。 

更好的是,如果你真的在这里使用它,在发生故障时使用删除之前。

  bool peekAndMark(T& t); //允许每个线程一个标记项目
void deleteMarked(); //如果项目被正确标记,弹出它。
void unmark(); //放弃标记。 (回滚)


Sometimes this implementation and execution of BlockingQueue just works. Sometimes it segfaults. Any idea why?

#include <thread>
using std::thread;
#include <mutex>
using std::mutex;
#include <iostream>
using std::cout;
using std::endl;
#include <queue>
using std::queue;
#include <string>
using std::string;
using std::to_string;
#include <functional>
using std::ref;

template <typename T>
class BlockingQueue {
private:
    mutex mutex_;
    queue<T> queue_;
public:
    T pop() {
        this->mutex_.lock();
        T value = this->queue_.front();
        this->queue_.pop();
        this->mutex_.unlock();
        return value;
    }

    void push(T value) {
        this->mutex_.lock();
        this->queue_.push(value);
        this->mutex_.unlock();
    }

    bool empty() {
        this->mutex_.lock();
        bool check = this->queue_.empty();
        this->mutex_.unlock();
        return check;
    }
};

void fillWorkQueue(BlockingQueue<string>& workQueue) {
    int size = 40000;
    for(int i = 0; i < size; i++)
        workQueue.push(to_string(i));
}

void doWork(BlockingQueue<string>& workQueue) {
    while(!workQueue.empty()) {
        workQueue.pop();
    }   
}

void multiThreaded() {
    BlockingQueue<string> workQueue;
    fillWorkQueue(workQueue);
    thread t1(doWork, ref(workQueue));
    thread t2(doWork, ref(workQueue));
    t1.join();
    t2.join();
    cout << "done\n";
}

int main() {
    cout << endl;

    // Multi Threaded
    cout << "multiThreaded\n";
    multiThreaded();
    cout << endl;
}

解决方案

See here:

What do I get from front() of empty std container?

Bad things happen if you call .front() on an empty container, better check .empty() first.

Try:

T pop() {
    this->mutex_.lock();
    T value;
    if( !this->queue_.empty() )
    {
        value = this->queue_.front();  // undefined behavior if queue_ is empty
                                       // may segfault, may throw, etc.
        this->queue_.pop();
    }
    this->mutex_.unlock();
    return value;
}

Note: Since atomic operations are important on this kind of queue, I'd recommend API changes:

bool pop(T &t);  // returns false if there was nothing to read.

Better yet, if you're actually using this where it matters, you probably want to mark items in use before deleting in case of failure.

bool peekAndMark(T &t);  // allows one "marked" item per thread
void deleteMarked();     // if an item is marked correctly, pops it.
void unmark();           // abandons the mark. (rollback)

这篇关于创建阻止队列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆