服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++线程安全的队列你了解嘛

C++线程安全的队列你了解嘛

2022-10-14 13:18吃米饭 C/C++

这篇文章主要为大家详细介绍了C++线程安全的队列,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

C++线程安全的队列你了解嘛

无界队列

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include<queue>
#include<mutex>
#include<condition_variable>
#include<optional>
#include<cassert>
#include<thread>
template<typename T,typename Container = std::queue<T>>
class Queue //无界队列
{
public:
    Queue() = default;
    ~Queue() = default;
    //禁止拷贝和移动,编译器会自动delete
    /*Queue(const Queue&) = delete;
    Queue(Queue&&) = delete;
    Queue& operator=(const Queue&) = delete;
    Queue& operator=(Queue&&) = delete;*/
    void push(const T& val)
    {
        emplace(val);
    }
    void push(T&& val)
    {
        emplace(std::move(val));
    }
    template<typename...Args>
    void emplace(Args&&...args)
    {
        std::lock_guard lk{ mtx_ };
        q_.push(std::forward<Args>(args)...);
        cv_.notify_one();
    }
    T pop()//阻塞
    {
        std::unique_lock lk{ mtx_ };
        cv_.wait(lk, [this] {return !q_.empty(); });//如果队列不为空就继续执行,否则阻塞
        assert(!q_.empty());
        T ret{ std::move_if_noexcept(q_.front()) };
        q_.pop();
        return ret;
    }
    std::optional<T> try_pop()//非阻塞
    {
        std::unique_lock lk{ mtx_ };
        if (q_.empty())return {};
        std::optional<T> ret{ std::move_if_noexcept(q_.front()) };
        q_.pop();
        return ret;
    }
    bool empty()const
    {
        std::lock_guard lk{ mtx_ };
        return q_.empty();
    }
private:
    Container q_;
    mutable std::mutex mtx_;
    std::condition_variable cv_;
};
#include<iostream>
int main()
{
    Queue<int>q;
    std::thread t1(
        [&] {
            for (int i = 0; i < 100; ++i)
            {
                q.push(i);
            }
        });
    std::thread t2(
        [&] {
            for (int i = 0; i < 100; ++i)
            {
                //std::cout<<q.pop()<<" ";
                if (auto ret = q.try_pop())
                {
                    std::cout << *ret<<" ";
                }
            }
        });
    t1.join();
    t2.join();
    return 0;
}

有界队列

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include<mutex>
#include<condition_variable>
#include<boost/circular_buffer.hpp>
#include<optional>
template<typename T>
class Queue
{
public:
    Queue(size_t capacity) :q_{ capacity }{}
    template<typename T>
    void push(T&& val)//阻塞
    {
        std::unique_lock lk{ mtx_ };
        not_full_.wait(lk, [this] {return !q_.full(); });
        assert(!q_.full());
        q_.push_back(std::move(std::forward<T>(val)));
        not_empty_.notify_one();
    }
    template<typename T>
    bool try_push(T&& val)//非阻塞
    {
        std::lock_guard lk{ mtx_ };
        if (q_.full())return false;
        q_.push_back(std::forward<T>(val));
        not_empty_.notify_one();
        return true;
    }
    T pop()//阻塞
    {
        std::unique_lock lk{ mtx_ };
        not_empty_.wait(lk, [this] {return !q_.empty(); });
        asert(!q_.empty());
        T ret{ std::move_if_noexcept(q_.front()) };
        q_.pop_front();
        not_full_.notify_one();
        return ret;
    }
    std::optional<T> try_pop()//非阻塞
    {
        std::lock_guard lk{ mtx_ };
        if (q_.empty())return {};
        std::optional<T> ret{ std::move_if_noexcept(q_.front()) };
        q_.pop_front();
        not_full_.notify_one();
        return ret;
    }
private:
    boost::circular_buffer<T>q_;
    std::mutex mtx_;
    std::condition_variable not_full_;
    std::condition_variable not_empty_;
};
#include<iostream>
int main()
{
    Queue<int>q(10);
    std::thread t1(
        [&] {
            for (int i = 0; i < 100; ++i)
            {
                q.push(i);
            }
        });
    std::thread t2(
        [&] {
            for (int i = 0; i < 100; ++i)
            {
                //std::cout<<q.pop()<<" ";
                if (auto ret = q.try_pop())
                {
                    std::cout << *ret << " ";
                }
            }
        });
    t1.join();
    t2.join();
    return 0;
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注服务器之家的更多内容! 

原文链接:https://blog.csdn.net/Cdreamfly/article/details/123365671

延伸 · 阅读

精彩推荐
  • C/C++二叉搜索树源码分享

    二叉搜索树源码分享

    这篇文章主要介绍了二叉搜索树源码,需要的朋友可以参考下...

    C语言程序设计5312021-01-18
  • C/C++判断整数序列是否为二元查找树的后序遍历结果的解决方法

    判断整数序列是否为二元查找树的后序遍历结果的解决方法

    本篇文章是对判断整数序列是否为二元查找树的后序遍历结果的解决方法进行了详细的分析介绍,需要的朋友参考下...

    C语言教程网4082020-12-11
  • C/C++c++ bitset详解

    c++ bitset详解

    这篇文章主要介绍了C++ bitset用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起...

    IOUIUY4702021-12-21
  • C/C++C语言实现简单五子棋游戏

    C语言实现简单五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现简单五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    爱学代码的学生5482022-02-22
  • C/C++基于C语言实现简单的走迷宫游戏

    基于C语言实现简单的走迷宫游戏

    这篇文章主要介绍了基于C语言实现简单的走迷宫游戏,用到双向队列,方便在运行完毕后输出经过的点,文中示例代码介绍的非常详细,具有一定的参考价...

    LiaoGlenn12062021-03-30
  • C/C++C语言边角料2:用纯软件来代替Mutex互斥锁

    C语言边角料2:用纯软件来代替Mutex互斥锁

    在 Linux 系统中,当多个线程并行执行时,如果需要访问同一个资源,那么在访问资源的地方,需要使用操作系统为我们提供的同步原语来进行保护。同步原...

    IOT物联网小镇7032021-03-23
  • C/C++opencv求解区域的内接矩形

    opencv求解区域的内接矩形

    这篇文章主要为大家详细介绍了opencv求解区域的内接矩形,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    cfqcfqcfqcfqcfq5682021-09-16
  • C/C++while和for可以相互转换的例子分享

    while和for可以相互转换的例子分享

    这篇文章主要介绍了while和for可以相互转换的例子,需要的朋友可以参考下...

    C语言教程网4542021-01-15