2022-11-11 C++并发编程( 四十一 )

本文介绍了如何使用C++的并发编程特性,如`std::future`和`std::promise`,来测试空队列在多线程环境下的push和pop操作。通过构造同步环境并分析可能的结果,展示了如何确保线程安全和正确性。
摘要由CSDN通过智能技术生成


前言

多线程测试较单线程测试难一些, 需要制造一个多线程并发同步环境, 多次测试, 因为并发的乱序, 很多结果是随机的, 需要足够多的次数.

本文实现一个简单的并发测试结构, 用于测试并发代码.


一、测试空队列同时 pop, push

测试并发代码, 需要一个并发环境, 下面的实现是用 async 和 future 保证在多线程上进行, 用 promise 和 future 保证同步, 通过断言进行检查结果.

一个空队列, 同时进行 pop 和 push 有两种结果,

第一, push 在先, pop 在后, 没有问题, 断言通过

第二, pop 在先, push 在后, 则 pop 只能失败, 而后队列 push 成功, 含有一个元素, 断言失败.

以下实现的结构代码简单, 可扩展到更多线程的同步.

#include "ThreadSafeQueue_2.h"
#include <cassert>
#include <future>
#include <iostream>
#include <thread>

// 测试并发空队列 push 和 pop
void testConcurrentPushAndPopOnEmptyQueue()
{
    // 新建队列
    TS::threadSafeQueue<int> queue;

    // 为同步阻塞准备的 promise
    std::promise<void> go;
    std::promise<void> pushReady;
    std::promise<void> popReady;

    // 用于同步的 future
    std::shared_future<void> const ready(go.get_future());

    // 获取结果的 future
    std::future<void> pushDone;
    std::future<std::shared_ptr<int>> popDone;

    try
    {
        // 通过 async 封装测试函数 push
        pushDone =
            std::async(std::launch::async, [&queue, ready, &pushReady]() {
                // 设置值用于解除 push 阻塞
                pushReady.set_value();
                // 阻塞用于同步
                ready.wait();
                // 测试 push
                queue.push(42);
            });

        // 通过 async 封装测试函数 pop
        popDone = std::async(std::launch::async, [&queue, ready, &popReady]() {
            // 设置值用于解除 pop 阻塞
            popReady.set_value();
            // 阻塞用于同步
            ready.wait();

            // const int result = *queue.tryPop();

            // 测试 trypop
            return queue.tryPop();
        });

        // 阻塞等待
        pushReady.get_future().wait();
        popReady.get_future().wait();

        // 解除阻塞, 开启同步
        go.set_value();

        // 返回结果
        pushDone.get();

        // 断言结果
        assert(queue.empty());
        assert(*popDone.get() == 42);
    }
    // 捕捉异常
    catch (...)
    {
        go.set_value();
        throw;
    }
}

auto main() -> int
{
    // 开始测试
    testConcurrentPushAndPopOnEmptyQueue();

    return 0;
}

总结

多线程测试由于存在不确定顺序, 通常结果是多样的, 需要多次测试.

C++ 标准库可以很容易的通过 promise 和 future 达成同步, 同时利用 async 实现多线程, 析构对 future 进行线程汇入, 不必担心线程安全问题.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不停感叹的老林_<C 语言编程核心突破>

不打赏的人, 看完也学不会.

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值