zoukankan      html  css  js  c++  java
  • C++ 11 thread 基础用法 lock unlock join mutex joinable lock_guard unique_lock condition_variable wait notify_one notify_all asnyc future packaged_task promise

    #include "pch.h"
    #include<iostream>
    #include<string>
    #include<vector>
    #include<list>
    // 线程相关头文件
    #include<thread>
    #include<mutex>
    #include<future>
    using namespace std;

    static int res = 0; //共享变量 演示使用互斥量读写。

    mutex my_mutex; //互斥量
    mutex my_mutex2;
    void test() //不带参数
    {
    auto id=this_thread::get_id();
    cout << "无参数id="<<id << endl;
    /* 互斥量保护数据的lock 和unlock形式 */
    my_mutex.lock();
    // lock(my_mutex, my_mutex2); 相当于同时lock了所有互斥量
    res = 1;
    my_mutex.unlock(); //成双成对。
    return;
    }
    void test2(int )
    {
    auto id = this_thread::get_id();
    cout << "带参数id="<<id <<endl;
    /*
    互斥量保护数据的lock_guard 形式。
    参数有adopt_lock(结构体对象)作用是表示互斥量已经lock了。
    */
    lock_guard<mutex>my_lock(my_mutex); //lock_guard<mutex>my_lock(my_mutex,adopt_lock); 。
    res = 2;
    return;
    }
    class A
    {
    public:
    void operator()() //不能带参数
    {
    auto id = this_thread::get_id();
    cout << "类对象id="<<id << endl;
    return;
    }
    //call_once
    static void once()
    {
    return;
    }
    };
    void second()
    {
    return;
    }
    void my_async();
    void my_packaged();
    void my_promise_();
    void myfuture();
    int main()
    {
    int temp;
    thread my_thread(test);
    //第一个参数为可调用对象,包括函数,类(必须定义了()重载运算符),lambda表达式,后续参数为函数对应参数。
    thread my_thread2(test2,temp);
    // join 等待子线程执行完毕再回到主线程

    if (my_thread.joinable()) //joinable判断子线程是否能join/detach
    {
    my_thread.join();
    }
    //一个线程只能join一次
    my_thread2.join();
    /* detach 不等待子线程 (尽量不使用)
    my_thread.detach();
    my_thread2.detach();
    */
    A a;
    thread my_thread3(a);
    my_thread3.join();

    //call_once()具备互斥量能力,保证函数只执行一次 并且更高效。需要结合标记once_flag(也是一个结构)使用
    once_flag g_flag;
    once_flag p_flag;
    call_once(g_flag, A::once);
    call_once(p_flag, second);
    //async future 相关。
    my_async();
    my_packaged();
    my_promise_();
    myfuture();
    cout << "I love China!" << endl;
    return 0;
    }

    // 更灵活的 unique_lock 类模板。 可以取代lock_guard 不需要自己unlock 第二个参数有adopt_lock(同lock_guard,前提是先lock)


    //try_to_lock(前提是不能先lock,不阻塞线程。)

    // defer_lock(前提是不能先lock,初始化不加锁的mutex) 可以直接调用成员函数。

    // 成员函数lock()

    //unlock()

    //try_lock() my_unique。try_lock()==true 表示拿到锁,没拿到锁就干其他事。

    // release() 返回mutex对象指针 并释放所有权 mutex *ptr=my_unique.release(); ptr->unlock();

    //unique_lock<mutex>my_unique(my_mutex) 锁住的代码越少,粒度越细。

    //unique_lock<mutex>my_unique2(move::my_unique) //所有权转移

    /*------------------------------------------------------------------------------

    condition_variable wait() notify_one notify_all

    condition_variable my_cond 生成条件变量对象,需要互斥量配合工作

    wait 等待 notify_one 唤醒 notify_all 唤醒所有wait

    ------------------------------------------------------------------------------*/

    condition_variable my_cond;
    mutex my_mutex3;
    bool juge()
    {
    if (true)
    {
    return true;
    }
    return false;
    }

    void outmsg()
    {
    int command = 0;
    while (true)
    {
    unique_lock<mutex>my_mu(my_mutex3);
    my_cond.wait(my_mu, juge);

    //第二个参数返回false 那么解锁互斥量,并堵塞,直到其他线程调用notify_once()成员函数为止。
    //第二个参数缺省值为false

    //一顿操作。。。

    //可以防止后续操作缺少条件(比如共享消息队列没有消息无法读取则需要wait 写操作写入数据。)

    //mes.pop_back() 读取第一条消息。

    break;
    }
    }

    void inmsg()
    {
    for (int i = 0;i < 100000;++i)
    {
    unique_lock<mutex>my_mu(my_mutex3);
    //一顿操作
    my_cond.notify_one(); //尝试唤醒wait() mutex锁之后被释放了。

    //notify_all() 唤醒所有wait();
    }

    }
    /*------------------------------------------------------------------------------

    async 启动一个异步任务(自动创建一个线程)并返回值,返回future类模板。 (也可能是同步任务)

    async 未必创建线程

    future 提供访问异步操作返回结果的机制。

    packaged_task 包装函数

    promise 类模板,在某个线程中赋值,在另一个线程中提取 promise<int>my_promise;

    ------------------------------------------------------------------------------*/

    int mythread()
    {
    auto id = this_thread::get_id();
    cout << "async 的 id=" << id << endl;
    //使线程睡觉5秒
    chrono::milliseconds dura(5000);
    this_thread::sleep_for(dura);
    cout << "async 的 id=" << id << endl;
    return 5;
    }

    void my_async()
    {
    //future<int>result = async(mythread);
    //缺省参数为async | deferred 系统决定是(创建新线程)还是(不创建新线程)

    future<int>result = async(launch::deferred,mythread); //如果是调用类的成员函数 future<int>result = async(&A::mythread,&Aobj,成员函数参数);

    //asnyc可以接受额外参数 std::launch枚举类型

    //thread()由于系统资源紧张可能创建失败,并且难以拿到函数返回值

    //deferred 延迟调用,直到调用get()和wait()任务才执行,如果没这两函数,那么函数不会被执行。(没有新线程)

    //async强制这个异步任务在新线程上执行。线程数量不应该超过100--200 !

    cout << "continue....." << endl;
    cout << "continue....." << endl;
    cout << "continue....." << endl;
    cout << "continue....." << endl;
    //用get()返回线程结果。不拿到返回值誓不罢休。
    cout << "async返回的结果="<<result.get() << endl;
    return;
    }
    int mythread1(int mypt)
    {
    return mypt;
    }

    void my_packaged()
    {
    packaged_task<int(int)>mypt(mythread1);

    /* lambda表达式
    packaged_task<int(int)>mypt([](int mypar)
    {

    }
    ); */

    thread my_pt(ref(mypt), 1);
    my_pt.join();
    future<int>res = mypt.get_future();
    cout << "packaged返回结果:"<<res.get() << endl;
    return;
    }

    void my_promise(promise<int>&temp,int cur)
    {
    cur++;
    cur *= 10;
    int result = cur; //保存结果
    temp.set_value(result); //结果放在promise之中

    }

    void my_promise_()
    {
    promise<int>myprom;
    thread t(my_promise, ref(myprom), 10);
    t.join();
    future<int>fu = myprom.get_future();
    int result=fu.get();
    cout << "promise结果=" << result<<endl;
    return;
    }


    /*------------------------------------------------------------------------------
    future 的其他成员函数,其中get是移动语义 只能调用一次。 如果好几个线程都用到某个线程的结果,就不能使用get了。 要用到shared_future

    shared_future 也是个类模板。

    原子操作atomic 无锁方式的多线程并发技术 在多线程中不会被打断的程序执行片段。

    原子操作只针对一个变量,而不是一个代码段。atomic是个类模板,封装某个类型变量。

    用于简单统计。 支持 ++ -- += &= |= ^= 其他未必支持
    atomic<int> my_atomic=0;
    auto temp=my_atomic //这种操作不被允许。甚至不能相互赋值 atomic<int>temp= my_atomic
    只能以原子方式读auto temp(my_atomic.load()) | atomic<int>temp(my_atomic.load());
    原子方式写 store() =
    my_atomic++;
    atomic<bool>my_bool=false;
    my_bool=true;

    ------------------------------------------------------------------------------*/

    int my_future()
    {
    auto id = this_thread::get_id();
    cout << "future 的 id=" << id << endl;
    //使线程睡觉5秒
    chrono::milliseconds dura(5000);
    this_thread::sleep_for(dura);
    cout << "future 的 id=" << id << endl;
    return 5;
    }

    void myfuture()
    {

    future<int>result = async(my_future);
    //timeout
    future_status status = result.wait_for(chrono::seconds(1));

    //ready
    //future_status status = result.wait_for(chrono::seconds(6));

    //deferred
    //future<int>result = async(launch::deferred,my_future);

    if (status == future_status::deferred) //取决于 async是否使用launch::deferred (或者默认值) 没有创建线程
    {
    cout << "延迟执行了亲!" << endl;
    cout << "真正执行了亲!" << result.get() << endl;
    }
    else //创建了线程
    {
    if (status == future_status::timeout)
    {
    cout << "超时了亲!" << endl;
    }
    else if (status == future_status::ready)
    {
    cout << "正常了亲!" << result.get() << endl;
    }
    }

    /*
    bool canget = result.valid();//canget 为true
    int temp = result.get(); //该语句只能执行一次
    canget = result.valid(); // canget 为false 因为get()之后值给了temp
    */
    shared_future<int>result_s(move(result)); //执行完result结果为空,转移到result_s
    //shared_future<int>result_s(result.share()); //等同于使用移动语义move

    auto temp = result_s.get(); //该语句可以执行多次

    //shared_future << int > result_s(mypt.get_future(); 用packaged_task 直接构建shared_future

    }


    /*-----------------------------------------------

    windows临界区
    同一个线程多次进入临界区(调用两次enter和leave)无需等待 不同线程就需要等待了。mutex则会报错
    自动析构技术
    lock_guard unique_lock 对于临界区,构造的时候enter 析构的时候leave RAII类(资源获取即初始化)

    recursive_mutex 递归的独占互斥量 创建方法 recursive_mutex my_mutex
    用于处理一个函数多次调用lock() (使用metux时, 两个函数都有锁,但是其中一个函数调用了另一个,则程序会报错。)

    带超时的独占互斥量

    time_mutex 和 recursive_time_mutex
    try_lock_for(time); 时间内拿到锁为true 超时则为false 流程可以往下走。
    try_lock_until(time); 未来时间内拿到锁就true,超时则为false
    #include<windows.h>

    CRITICAL_SECTION my_section; 类似于mutex

    InitializeCriticalSection(&my_section)初始化
    EnterCriticalSection(&my_section) 相当于lock()
    LeaveCriticalSection(&my_section) 相当于unlock()


    -------------------------------------------------*/

    /*-----------------------------------------------
    线程池 :把多个线程弄到一起,循环利用,统一管理
    线程无法创建太多,线程偶尔无法稳定工作
    实现方式:程序启动时,就创建一定数量线程

    线程极限数量:2000 再创建就奔溃了。
    数量建议:技术开发程序的开发商的建议。
    创建线程完成各种业务 100堵塞那么久开110

    -------------------------------------------------*/

  • 相关阅读:
    vue(21)初识Vuex
    ESCMScript6(3)Promise对象
    vue(20)生命周期函数
    vue(19)嵌套路由
    vue(18)路由懒加载
    vue(17)vue-route路由管理的安装与配置
    vue(16)vue-cli创建项目以及项目结构解析
    vue(15)vue-cli介绍与安装
    webpack(11)配置文件分离为开发配置、生成配置和基础配置
    webpack(10)webpack-dev-server搭建本地服务器
  • 原文地址:https://www.cnblogs.com/yangshengjing/p/11621238.html
Copyright © 2011-2022 走看看