
创建std :: thread,通常将其绑定到基础线程. 如果该线程仍绑定到该函数对象,则该函数将立即在该线程的基础线程上运行. 许多与线程相关的默认设置都是移动语义,因为线程复制在常识上是一种奇怪的行为. joinable(): 是否有可能阻塞绑定到该线程的底部线程以完成运行(如果该线程未绑定到底部线程等,则无法加入)join(): 该线程阻塞直到底部线程的线程完成运行. detach(): 绑定到该线程的基础线程被分离,并且该基础线程被允许继续运行(该线程失去了对基础线程的控制).
为了避免共享变量的多线程操作之间发生冲突,引入了互斥锁和锁.
通常与锁一起使用的Mutex也可以锁定自己(lock(),unlock()). 如果互斥锁被第二个锁定请求锁定,则第二个锁定所在的线程将被阻塞,直到第一个锁定被解锁. 简单的锁定,在施工期间要求锁定,并在释放时解锁,从而降低了性能量消耗的成本. 适用区域中的多线程互斥操作. 可以随时解锁或重新锁定更和更灵活的锁(减小锁的粒度),并且性能量消耗的成本比前者高一点. 多线程互斥操作可实现灵活区域.

原子变量是指单个最小的不可分变量(例如int),原子操作是指单个极小的操作(例如增量操作)
C ++原子类封装了此数据对象,因此对原子变量的多线程访问不会引起竞争. (您可以使用原子类来实现无锁设计)
这是一个原子布尔类型,可以支持两个原子操作. (实际上,互斥锁可以用atomic_flag实现). test_and_set(): 如果设置了atomic_flag对象,则返回true;否则,返回true. 如果未设置atomic_flag对象,则进行设置,并返回false. clear(): 清除atomic_flag对象. int,charc++11 多线程,bool和其他基本数据类型的原子封装(实际上,这是一个特殊的模板). store(): 修改封装的值. load(): 读取封装的值. 变量在每个线程中都是独立的(类似于静态变量),并程末尾释放.

condition变量通常用于为多个线程实现等待队列,即主线程通知工作已完成,并且等待队列中的其他线程将被唤醒并开始工作.
wait(std :: unique_lock
可以通过notify_one / notify_all唤醒添加正在等待的变量. 当调用该函数唤醒信号时c++11 多线程,等待条件变量将重新竞争互斥锁.

尚未获得互斥锁的线程将等待变形. 它将从等待信号量的队列转移到等待互斥量的队列. 一旦获得了互斥锁的所有权,它将继续向下执行,
但是这时,其他线程已经执行并重置了执行条件(例如,一个作业仅需要两个线程来执行,并在通知了两个线程之后重置了执行条件),这可能导致执行线程导致未定义的错误.
//不能应对虚假唤醒 if(pred()){ cv.wait(lock); }

//利用while重复判断执行条件,可以应对虚假唤醒 while(!pred()){ cv.wait(lock); }
//C++11提供了更方便的语法,将判断条件作为一个参数,实际上等价于前者 cv.wait(lock,pred);
构造它时,会生成一个未准备好的共享状态(包括存储的T值及其是否准备就绪). 您可以设置T值并使状态准备就绪. get_future(): 共享状态绑定到将来的对象. set_value(): 设置共享状态的T值,并让该状态准备就绪,然后绑定的将来对象可以是get(). 在构造期间绑定功能对象还会产生尚未准备好的共享状态. 通过线程启动或类似函数的形式启动函数对象. 但是与promise相比,没有set_value()公共接口,但是当执行绑定的函数对象时,执行结果返回值或抛出的异常将存储在共享状态中,可以通过std :: future对象进行访问. get_future(): 共享状态绑定到将来的对象. 用于访问共享状态(即获取值). 当将来状态未准备好时,调用绑定的promise,packaged_task和其他析构函数,它们将在期望中存储异常. std :: future有局限性,当有多个线程在等待时,只有一个线程可以获取等待结果. share(): 将相同的共享状态共享给另一个futurewait(): 如果共享状态尚未就绪,请阻塞直到就绪. get(): 获取共享状态的值. 如果共享状态尚未就绪,请阻塞直到就绪.
当需要多个线程来等待同一事件的结果(即对同一共享状态的多次访问)时,需要使用std :: shared_future代替std :: future. Shared_future与Future相似,但是可以复制shared_future,并且多个shared_futures可以共享共享状态的最终结果(即共享状态的某个值或例外). shared_future可以由future对象隐式转换,也可以由future :: share()显示. 无论进行哪种转换,转换后的将来对象都将成为函数的无效异步执行. 执行完函数后,使用std :: async将返回值绑定到futrue(实际上,它封装了thread和packed_task的函数,使异步执行任务更加容易). 如果创建std :: thread来执行异步行为,则基础硬件线程可能不足,从而导致错误. 而std :: async隐藏了这些底层细节. 如果使用默认参数,它将负责线程的创建和销毁,避免过载,并与标准库的线程管理组件保持平衡. 因此,请尝试使用任务驱动的异步操作设计,而不是线程驱动的线程设计. std :: async中的第一个参数是启动策略,它控制std :: async的异步行为. 我们可以使用三种不同的启动策略来创建std :: async:
std :: launch :: async参数保证异步行为,也就是说,传递函数将在单独的线程中执行.
std :: launch :: deferred参数当其他线程调用get()/ wait()访问共享状态时,将调用非异步行为.
std :: launch :: async | std :: launch :: deferred参数是默认行为. 通过这种启动策略,它可以异步运行或不能异步运行,具体取决于系统的负载.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-255272-1.html
千玺千玺千玺
质检的买到假东西来检验
台湾渔民敢去那捕鱼吗