future 扩展 、原子操作 std::atomic

一、future 扩展

1、future 的其他成员函数

class MyClass
{
public:
    int MyThread(int param);   // 假定一个线程函数是有返回值的
};

int main()
{
    MyClass ele;
    std::future<int> result = std::async(&MyClass::MyThread, &ele, 5);

    std::future_status status = result.wait_for(std::chrono::seconds(2));
    // 此时等待2秒。 返回示 result 绑定的线程执行了2秒之后,目前的状态
    if (status == std::future_status::timeout)
    {
        // 超时:表示线程还是没有执行完,即线程执行的时间超过2秒
        // 最终在主线程return 0 之前,会等待线程执行完
    }
    else if (status == std::future_status::ready)
    {
        // 表示线程成功返回
        // 此时可以得到线程执行后的结果
    }
    else if (status == std::future_status::deferred)
    {
        // 表示线程会被延迟创建,如果没有调用future.get() 函数,线程不会被创建
        // 与第一个参数 std::async() 第一个参数为 std::launch::deferred 的情况相同, 与下句意思相同
        // std::future<int> result = std::async(std::launch::deferred, &MyClass::MyThread, &ele, 5);
        result.get();  // 直到这句话才会执行
    }

    system("pause");
    return 0;
}

2、shared_future

// future.get() 函数是一个移动语义,所以只能调用一次 future的get()函数,否则会编译报错
// 如果一个线程中的结果,要被其他多个线程使用,则需要用std::shared_future
// std::shared_future 的 get() 函数是一个复制语义

std::future<int> result = std::async(&MyClass::MyThread, &ele, 5);
std::shared_future<int> result_s(std::move(result)); 
// std::shared_future<int> result_s(result.share()); 
// 这两种方式都可以,都是移动语义
// 执行完毕后,result_s有值,result为空
bool isHaveValue = result.valid();  // 可以通过这个函数来判断是否有值
auto myValue = result_s.get();   // 这种写法是复制语义,可以执行多次

二、原子操作 std::atomic

1、概述

    // 原子操作:可以理解成一种不需要用到互斥量技术的多线程并发变成方式
    // 原子操作:是在多线程中不会被打断的程序执行片段
    // 原子操作效率比互斥量效率上更好
    // 互斥量加锁一般是一个代码段,原子操作一般针对的是一个变量
    // 原子操作一般指“不可分割的操作”,操作状态要么是完成的,要么是未完成的,不会出现半完成状态

2、原子操作演示

int m_Int = 0;
std::mutex m_mutex;
std::atomic<int> m_automicInt = 0;    // std::atomic   类模板,是用来封装某个类型的值
// 封装了一个类型为int的对象,我们可以像操作一个int类型变量一样操作该值


// 假设多个线程的入口函数都是这个函数,
// 表示多个线程,都在改变m_int的值,则需要通过加锁技术来保证结果的正确性
void WriteIntValue()
{
    for (int i = 0; i < 10000; ++i)
    {
        m_automicInt++;  // 对应的操作是个原子操作,所以不会被打断
        // 如果此处用的是普通的int 类型,则需要加锁来执行
        //m_mutex.lock();
        //m_Int++;
        //m_mutex.unlock();
        m_automicInt += 1; // 结果正确
        m_automicInt = m_automicInt + 1;  // 结果错误:说明不是所有运算符都支持原子操作
        // 原子操作一般支持: ++  --  +=  &=  |=  ^= 这些运算符,其他可能不支持
    }
}

 

上一篇:Guava库学习:学习Concurrency(五)SettableFuture【转】


下一篇:Netty系列-netty的Future 和 Promise