从2个不同的线程访问相同的队列时陷入死锁

时间:2019-05-14 19:34:59

标签: c++ multithreading mutex deadlock condition-variable

我正在使用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如何知道哪些线程需要首先发出信号感到困惑。

0 个答案:

没有答案