c++11多线程操作

  • 线程

    • thread
    int main()
    {
    thread t1(Test1);
    t1.join();
    thread t2(Test2);
    t2.join();
    thread t3 = t1;
    thread t4(t1);
    thread t5 = std::move(t1);
    thread t6(std::move(t1));
    return 0;
    }

    t3,t4创建失败,因为thread的拷贝构造和赋值运算符重载的原型是:

    thread(const thread&) = delete;
    thread& operator=(const thread&) = delete;

    被禁用了,但是t5, t6线程是创建成功的。std::move把t1转换为右值,调用的是函数原型为thread& operator=(thread&& _Other) noexceptthread(thread&& _Other) noexcept

    当线程对象t1被移动拷贝和移动赋值给t5和t6的时候,t1就失去了线程控制权,也就是一个线程只能同时被一个线程对象所控制。最直观的是t1.joinable()返回值为false,joinable()函数后面介绍。

    使用类成员函数作为线程参数

    class Task
    {
    public:
    Task(){}
    void Task1() {}
    void Task2() {}
    private:
    }; int main()
    {
    Task task;
    thread t3(&Task::Task1, &task);
    t3.join();
    return 0;
    }

    关键点是要创建一个类对象,并作为第二个参数传入thread()线程的构造函数中去。

  • 管理当前线程的函数

    • yield

    此函数的准确性为依赖于实现,特别是使用中的 OS 调度器机制和系统状态。例如,先进先出实时调度器( Linux 的 SCHED_FIFO )将悬挂当前线程并将它放到准备运行的同优先级线程的队列尾(而若无其他线程在同优先级,则 yield 无效果)。

    #include <iostream>
    #include <chrono>
    #include <thread> // 建议其他线程运行一小段时间的“忙睡眠”
    void little_sleep(std::chrono::microseconds us)
    {
    auto start = std::chrono::high_resolution_clock::now();
    auto end = start + us;
    do {
    std::this_thread::yield();
    } while (std::chrono::high_resolution_clock::now() < end);
    } int main()
    {
    auto start = std::chrono::high_resolution_clock::now(); little_sleep(std::chrono::microseconds(100)); auto elapsed = std::chrono::high_resolution_clock::now() - start;
    std::cout << "waited for "
    << std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()
    << " microseconds\n";
    }
    • get_id

    这个函数不用过多介绍了,就是用来获取当前线程id的,用来标识线程的身份。

     std::thread::id this_id = std::this_thread::get_id();
    • sleep_for

    位于this_thread命名空间下,msvc下支持两种时间参数。

    std::this_thread::sleep_for(2s);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    • sleep_untile

    参数构建起来挺麻烦的,一般场景下要求线程睡眠的就用sleep_for就行了

    using std::chrono::system_clock;
    time_t tt = system_clock::to_time_t(system_clock::now());
    struct std::tm *ptm = localtime(&tt);
    std::this_thread::sleep_until(system_clock::from_time_t(mktime(ptm)));
  • 互斥

    • mutex

    对于互斥量看到一个很好的比喻:

    单位上有一台打印机(共享数据a),你要用打印机(线程1要操作数据a),同事老王也要用打印机(线程2也要操作数据a),但是打印机同一时间只能给一个人用,此时,规定不管是谁,在用打印机之前都要向领导申请许可证(lock),用完后再向领导归还许可证(unlock),许可证总共只有一个,没有许可证的人就等着在用打印机的同事用完后才能申请许可证(阻塞,线程1lock互斥量后其他线程就无法lock,只能等线程1unlock后,其他线程才能lock),那么,这个许可证就是互斥量。互斥量保证了使用打印机这一过程不被打断。

    代码示例:

    mutex mtx;
    
    int gNum = 0;
    void Test1()
    {
    mtx.lock();
    for(int n = 0; n < 5; ++n)
    gNum++;
    mtx.unlock();
    } void Test2()
    {
    std::cout << "gNum = " << gNum << std::endl;
    } int main()
    {
    thread t1(Test1);
    t1.join();
    thread t2(Test2);
    t2.join();
    return 0;
    }

    join()表示主线程等待子线程结束再继续执行,如果我们的期望是打印循环自增之后的gNum的值,那t1.join()就放在t2创建之前调用。因为t2的创建就标志着t2线程创建好然后开始执行了

    通常mutex不单独使用,因为lock和unlock必须配套使用,如果忘记unlock很可能造成死锁,即使unlock写了,但是如果在执行之前程序捕获到异常,也还是一样会死锁。如何解决使用mutex造成的死锁问题呢?下面介绍unique_gard和lock_guard的时候详细说明。

    • timed_mutex

    提供互斥设施,实现有时限锁定

    • recursive_mutex

    提供能被同一线程递归锁定的互斥设施

    • recursive_timed_mutex

    提供能被同一线程递归锁定的互斥设施,并实现有时限锁定

  • 通用互斥管理

    • lock_guard
    void Test1()
    {
    std::lock_guard<std::mutex> lg(mtx);
    for(int n = 0; n < 5; ++n)
    {
    gNum++;
    std::cout << "gNum = " << gNum << std::endl;
    }
    }
    int main()
    {
    thread t1(Test1);
    thread t2(Test1);
    t1.join();
    t2.join();
    return 0;
    }

    lock_guard相当于利用RAII机制(“资源获取就是初始化”)把mutex封装了一下,在构造中lock,在析构中unlock。避免了中间过程出现异常导致的mutex不能够正常unlock.

    • scoped_lock(c++17)
    • unique_lock
    • defer_lock_t
    • try_to_lock_t
    • adopt_lock_t
    • defer_lock
    • try_to_lock
    • adopt_lock
  • 通用锁算法

    • try_lock
    • lock
  • 单次调用

    • once_flag
    • call_once
  • 条件变量

    • condition_variable
    • condition_variable_any
    • notify_all_at_thread_exit
    • cv_status
  • Future

    • promise
    • packaged_task
    • future
    • shared_future
    • async
    • launch
    • future_status
    • Future错误
      • future_error
      • future_category
      • future_errc

c++11 新特性实战 (一):多线程操作的更多相关文章

  1. c++11新特性实战(二):智能指针

    c++11添加了新的智能指针,unique_ptr.shared_ptr和weak_ptr,同时也将auto_ptr置为废弃(deprecated). 但是在实际的使用过程中,很多人都会有这样的问题: ...

  2. [转载] C++11新特性

    C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章. 我是一名C++程序员,非常想了解一下C++11. 英文版的维基百科看起来非常费劲,而中文版维基百 ...

  3. c++学习书籍推荐《深入理解C++11 C++11新特性解析与应用》下载

    百度云及其他网盘下载地址:点我 编辑推荐 <深入理解C++11:C++11新特性解析与应用>编辑推荐:C++标准委员会成员和IBM XL编译器中国开发团队共同撰写,权威性毋庸置疑.系统.深 ...

  4. c++ 11 线程池---完全使用c++ 11新特性

    前言: 目前网上的c++线程池资源多是使用老版本或者使用系统接口实现,使用c++ 11新特性的不多,最近研究了一下,实现一个简单版本,可实现任意任意参数函数的调用以及获得返回值. 0 前置知识 首先介 ...

  5. C++11新特性总结 (二)

    1. 范围for语句 C++11 引入了一种更为简单的for语句,这种for语句可以很方便的遍历容器或其他序列的所有元素 vector<int> vec = {1,2,3,4,5,6}; ...

  6. C++11新特性总结 (一)

    1. 概述 最近在看C++ Primer5 刚好看到一半,总结一下C++11里面确实加了很多新东西,如果没有任何了解,别说自己写了,看别人写的代码估计都会有些吃力.C++ Primer5是学习C++1 ...

  7. 在C++98基础上学习C++11新特性

    自己一直用的是C++98规范来编程,对于C++11只闻其名却没用过其特性.近期因为工作的需要,需要掌握C++11的一些特性,所以查阅了一些C++11资料.因为自己有C++98的基础,所以从C++98过 ...

  8. C++11新特性——range for

    很多编程语言都有range for语法功能,自C++11起,终于将这个重要功能加入C++标准中.range for语句,可以方便的遍历给定序列中的每个元素并对其执行某种操作. 1.基本语法 for(d ...

  9. C++11 新特性之智能指针(shared_ptr, unique_ptr, weak_ptr)

    这是C++11新特性介绍的第五部分,涉及到智能指针的相关内容(shared_ptr, unique_ptr, weak_ptr). shared_ptr shared_ptr 基本用法 shared_ ...

随机推荐

  1. Leetcode 24. Swap Nodes in Pairs(详细图解一看就会)

    题目内容 Given a linked list, swap every two adjacent nodes and return its head. You may not modify the ...

  2. .NET ORM 导航属性【到底】可以解决什么问题?

    写在开头 从最早期入门时的单表操作, 到后来接触了 left join.right join.inner join 查询, 因为经费有限,需要不断在多表查询中折腾解决实际需求,不知道是否有过这样的经历 ...

  3. 码云git clone报错Incorrect username or password ( access token )

    使用码云将仓库clone到本地,报错信息如下: D:\>git clone https://gitee.com/ycyzharry/helloworld.git Cloning into 'he ...

  4. e3mall商城的归纳总结7之solr搭建和应用

    敬给读者的话 本文主要应用的技术是solr技术的搭建和应用,本文小编尽量写的更详细一些,让读者在不考虑项目的情况下也能正常完成solr的搭建,说完搭建之后,再说明运行solrj在项目中如何应用solr ...

  5. 复制一个Python全部环境到另一个环境

    导出此环境下安装的包的版本信息清单  pip freeze > requirements.txt   联网,下载清单中的包到all-packet文件夹 [root@localhost ~]# p ...

  6. Android开发之第三方推送JPush极光推送知识点详解 学会集成第三方SDK推送

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 下面是一些知识点介绍,后期将会带领大家进行代码实战: 一.Android实现推送方式解决方案: 1.推 ...

  7. iview table render 进阶(一)

    Qestion: 如何给表格添加hover 事件? step1:  添加 domProps 选项参数 step2:  废话不多说,直接看demo code render: (h, params) =& ...

  8. P1004 方格取数(四维动态规划)

    题目描述 设有N \times NN×N的方格图(N \le 9)(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字00.如下图所示(见样例): A 0 0 0 0 0 0 0 0 ...

  9. House of Orange

    题目附件:https://github.com/ctfs/write-ups-2016/tree/master/hitcon-ctf-2016/pwn/house-of-orange-500 查看程序 ...

  10. 零基础一分钟入门Python

    这篇文章面向所有想学python的小伙伴(甚至你从没听过编程),这篇文章将会带你以最快的速度入门python.赶快上车,时间来不及了... 一,下载和安装python 1.下载: 1.1 python ...