C++并发多线程--std::future_status、std::shared_future和std::atomic的使用

目录

1--std::future_status的使用

2--std::shared_future的使用

3--std::atomic的使用


1--std::future_status的使用

        std::future_status成员函数含有三种状态:timeout(执行超时)、ready(执行完毕)和deferred(延迟执行),其中 deferred 状态需要用 std::launch::deferred 对线程进行设置,使其延迟直到 get() 或者 wait() 被调用;

#include 
#include 
#include 
#include 
 
class Sample{
public:
    // 线程入口函数
    int thread(int value){
        std::cout << "thread id: " << std::this_thread::get_id() << std::endl;
        std::chrono::seconds dura(value); // rest
        std::this_thread::sleep_for(dura);
        return 5;
    }
 
};
 
int main(int argc, char *argv[]){
    Sample sample;
    int value = 5;
    std::cout << "thread id: " << std::this_thread::get_id() << std::endl;
    std::future result = std::async(&Sample::thread, &sample, value);

    // 等待1s
    std::future_status status = result.wait_for(std::chrono::seconds(1));

    if (status == std::future_status::timeout){ // 超时,因为线程里面睡眠了5s
        // if判断为true,表明线程还没执行完,超时了
        std::cout << "thread timeout!" << std::endl;
    }
    else if(status == std::future_status::ready){ // 线程在等待期间成功返回
        std::cout << "result.get(): " << result.get() << std::endl;
    }
    // std::launch::deferred设置延迟执行状态
    // std::future result = std::async(std::launch::deferred, &Sample::thread, &sample, value);
    else if(status == std::future_status::deferred){ // 延迟执行状态
        std::cout << "deferred, result.get(): " << result.get() << std::endl;
    }
 
    std::cout << "main thread continue ..." << std::endl;
    return 0;
}

2--std::shared_future的使用

        由于 std::future 对象只能被 get() 一次(get()的实现基于移动语义),当多个线程都需要 std::future 对象 get() 的结果时,就会出错;

        std::shared_future 对象可以很好地解决上述问题;

#include 
#include 
#include 
#include 
 
// 线程入口函数
int thread(int value){
    std::cout << "thread id: " << std::this_thread::get_id() << std::endl;
    std::chrono::seconds dura(value); // rest
    std::this_thread::sleep_for(dura);
    return 5;
}
 
int main(int argc, char *argv[]){
    // std::packaged_task 打包任务
    std::cout << "thead id: " << std::this_thread::get_id() << std::endl;
    std::packaged_task mypt(thread);
    int value = 5;
    std::thread thread1(std::ref(mypt), value);
    thread1.join();
    // std::future result = mypt.get_future(); // std::future对象
    std::shared_future share_result(mypt.get_future()); // std::shared_future对象
    // 可以多次调用
    std::cout << "result.get(): " << share_result.get() << std::endl;
    std::cout << "result.get(): " << share_result.get() << std::endl;
    return 0;
}

3--std::atomic的使用

        原子操作:可以理解为在多线程并发中不会被打断的程序(不可分割的操作),其效率相对互斥量的加锁解锁更高;

        互斥量的加锁一般针对代码段(多代码),原子操作一般针对单个变量(单个程序语句);

        std::atomic用于将一个变量封装为原子对象,针对该变量的原子操作不会被打断(一般只针对于++, --, +=等操作符,其它复杂的语句仍可能被打断)

#include 
#include 
#include 
#include 

std::atomic global_count(0);

void thread(){
    for(int i =0; i < 100000; i++){
        global_count++; // 对应的操作为原子操作,不会被打断
    }
}

int main(int argc, char *argv[]){

    std::thread thread1(thread);
    std::thread thread2(thread);
    thread1.join();
    thread2.join();

    // 原子操作:可以理解为在多线程并发中不会被打断的程序(不可分割的操作),其效率相对互斥量的加锁解锁更高
    // 互斥量的加锁一般针对代码段(多代码),原子操作一般针对单个变量(单个程序语句)
    // std::atomic用于将一个变量封装为原子对象,针对该变量的原子操作不会被打断
    std::cout << "global_count: " << global_count << std::endl;
    return 0;
}
#include 
#include 
#include 
#include 

std::atomic end_flag(false);

void thread(){
    std::chrono::seconds dura(1);
    while(end_flag != true){
        std::cout << "Running thread: " << std::this_thread::get_id() << std::endl;
        std::this_thread::sleep_for(dura);
    }
    std::cout << "thread: " << std::this_thread::get_id() << " ended" << std::endl;
}

int main(int argc, char *argv[]){

    std::thread thread1(thread);
    std::thread thread2(thread);

    std::chrono::seconds dura(3);
    std::this_thread::sleep_for(dura);
    end_flag = true; // 原子操作,不可被打断
    thread1.join();
    thread2.join();
    std::cout << "main thread end all threads" << std::endl;
    return 0;
}

你可能感兴趣的:(多线程并发学习笔记,c++)