C++11线程使用总结
std::thread 在 <thread> 头文件中声明,因此使用 std::thread 需包含 <thread> 头文件。
<thread> 头文件摘要
<thread> 头文件声明了 std::thread 线程类及 std::swap (交换两个线程对象)辅助函数。另外命名空间 std::this_thread 也声明在 <thread> 头文件中。下面是 C++11 标准所定义的 <thread> 头文件摘要:
参见 N3242=11-0012 草案第 30.3 节 Threads(p1133)。
[cpp] view plain copy
amespace std {
#define __STDCPP_THREADS__ www.2636666.cn__cplusplus
class thread;
void swap(thread& x, thread& y);
namespace this_thread {
thread::id get_id();
void yield();
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep, Period>& rel_time);
}
}
<thread> 头文件主要声明了 std::thread 类,另外在 std::this_thread 命名空间中声明了get_id,yield,sleep_until 以及 sleep_for 等辅助函数,本章稍微会详细介绍 std::thread 类及相关函数。
std::thread 类摘要
std::thread 代表了一个线程对象,C++11 标准声明如下:
[cpp] view plain copy
namespace std {
class thread {
public:
// 类型声明:
class id;
typedef implementation-defined native_handle_type;
// 构造函数、拷贝构造函数和析构函数声明:
thread() noexcept;
template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
~thread();
thread(const thread&) = delete;
thread(thread&&) noexcept;
thread& operator=(const thread&) = delete;
thread& operator=(thread&&) noexcept;
// 成员函数声明:
void swap(thread&) noexcept;
bool joinable() const noexcept;
void join();
void detach();
id get_id() const noexcept;
native_handle_type native_handle(www.furong157.com);
// 静态成员函数声明:
static unsigned hardware_concurrency(www.huarenyl.cn ) noexcept;
};
}
std::thread 中主要声明三类函数:(1). 构造函数、拷贝构造函数及析构函数;(2). 成员函数;(3). 静态成员函数。另外,std::thread::id 表示线程 ID,同时 C++11 声明如下:
[cpp] view plain copy
namespace std {
class thread::id {
public:
id() noexcept;
};
bool operator==(thread::id x, thread::id www.thd178.com y) noexcept;
bool operator!=(thread::id x, thread::id www.yongshiyule178.com y) noexcept;
bool operator<(thread::id x, thread::id y) noexcept;
bool operator<=(thread::id x, thread::id y) noexcept;
bool operator>(thread::id x, thread::id y) noexcept;
bool operator>=(thread::id x, thread::id y) noexcept;
template<class charT, class traits>
basic_ostream<charT, traits>&
operator<< (basic_ostream<charT, traits>& out, thread::id id);
// Hash 支持
template <class T> struct hash;
template <> struct hash<thread::id>;
}
std::thread 详解
std::thread 构造和赋值
std::thread 构造函数
默认构造函数 (1) thread() noexcept;
初始化构造函数 (2) template <class Fn, class... Args>
explicit thread(Fn&& fn, Args&&... args);
拷贝构造函数 [deleted] (3) thread(const thread&) = delete;
Move 构造函数 (4) thread(thread&& x) noexcept;
默认构造函数(1),创建一个空的 std::thread 执行对象。
初始化构造函数(2),创建一个 std::thread 对象,该 std::thread 对象可被 joinable,新产生的线程会调用 fn 函数,该函数的参数由 args 给出。
拷贝构造函数(被禁用)(3),意味着 std::thread 对象不可拷贝构造。
Move 构造函数(4),move 构造函数(move 语义是 C++11 新出现的概念,详见附录),调用成功之后 x 不代表任何std::thread 执行对象。
线程状态:
在一个线程的生存期内,可以在多种状态之间转换,不同的操作系统可以实现不同的线程模型,定义许多不同的线程状态,每个状态还可以包含多个子状态,但大体来说,如下几种状态是通用的:
1)就绪:参与调度,等待被执行,一旦被调度选中,立即开始执行
2)运行:占用CPU,正在运行中
3)休眠:暂不参与调度,等待特定事件发生
4)中止:已经运行完毕,等待回收线程资源
线程环境:
线程存在于进程之中,进程内所有全局资源对于内部每个线程都是可见的。
进程内典型全局资源如下:
1)代码区:这意味着当前进程空间内所有的可见的函数代码,对于每个线程来说,也是可见的
2)静态存储区:全局变量,静态空间
3)动态存储区:堆空间
线程内典型的局部资源:
1)本地栈空间:存放本线程的函数调用栈,函数内部的局部变量等
2)部分寄存器变量:线程下一步要执行代码的指针偏移量
C++中的thread对象通常来说表达了执行的线程(thread of execution)。我在使用多线程的时候,发现很多情况下都是用join()函数,但是在使用detach的时候效果明显就是不一样了。
当thread::join()函数被调用后,调用它的线程会被block,join的作用是让主线程等待直到线程的执行被完成。基本上,这是一种可以用来知道一个线程已结束的机制。main是等待子线程结束才继续执行。当thread::join()返回时,OS的执行的线程已经完成,C++线程对象可以被销毁。
当thread::detach()函数被调用后,执行的线程从线程对象中被分离,该线程被从主线程分离出去放置到后台执行。已不再被一个线程对象所表达--这是两个独立的事情。C++线程对象可以被销毁,同时OS执行的线程可以继续。如果程序想要知道执行的线程何时结束,就需要一些其它的机制。join()函数在那个thread对象上不能再被调用,因为它已经不再和一个执行的线程相关联。没有thread对象指向该线程而失去了对它的控制,当对象析构时线程会继续在后台执行,但是当主程序退出时并不能保证线程能执行完。如果没有良好的控制机制或者这种后台线程比较重要,最好不用detach而应该使用join。
去销毁一个仍然可以“joinable”的C++线程对象会被认为是一种错误。为了销毁一个C++线程对象,约么join()函数需要被调用(并结束),要么detach()函数被调用。如果一个C++线程对象当销毁时仍然可以被join,异常会被抛出。
mutex:
mutex是用来保证线程同步的,防止不同的线程同时操作同一个共享数据。
示例代码:
[cpp] view plain copy
int cnt= 20;
mutex m;
void t1()
{
while (cnt > 0)
{
m.lock();
if (cnt > 0)
{
--cnt;
cout << cnt << endl;
}
m.unlock();
}
}
void t2()
{
while (cnt > 0)
{
m.lock();
if (cnt > 0)
{
--cnt;
cout << cnt << endl;
}
m.unlock();
}
}
int main()
{
thread th1(t1);
thread th2(t2);
th1.join();
th2.join();
return 0;
}
运行结果,cnt是依次递减的,没有因为多线程而打乱次序:
lock_guard:
使用lock_guard则相对安全,它是基于作用域的,能够自解锁,当该对象创建时,它会像m.lock()一样获得互斥锁,当生命周期结束时,它会自动析构(unlock),不会因为某个线程异常退出而影响其他线程。
[cpp] view plain copy
int cnt = 20;
mutex m;
void t1()
{
while (cnt > 0)
{
lock_guard<mutex> lockGuard(m);
if (cnt > 0)
{
--cnt;
cout << cnt << endl;
}
}
}
void t2()
{
while (cnt > 0)
{
lock_guard<mutex> lockGuard(m);
if (cnt > 0)
{
--cnt;
cout << cnt << endl;
}
}
}
get_id:
获取线程 ID,返回一个类型为 std::thread::id 的对象
示例如下:
[cpp] view plain copy
#include <iostream>
#include <thread>
#include <chrono>
void foo()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
std::thread t1(foo);
std::thread::id t1_id = t1.get_id();
std::thread t2(foo);
std::thread::id t2_id = t2.get_id();
std::cout << "t1‘s id: " << t1_id << ‘\n‘;
std::cout << "t2‘s id: " << t2_id << ‘\n‘;
t1.join();
t2.join();
}
sleep_until:
线程休眠至某个指定的时刻(time point),该线程才被重新唤醒。
[cpp] view plain copy
template< class Clock, class Duration >
void sleep_until( const std::chrono::time_point<Clock,Duration>& sleep_time );
sleep_for:
线程休眠某个指定的时间片(time span),该线程才被重新唤醒,不过由于线程调度等原因,实际休眠时间可能比sleep_duration 所表示的时间片更长。
[cpp] view plain copy
template< class Rep, class Period >
void sleep_for( const std::chrono::duration<Rep,Period>& sleep_duration );
#include <iostream>
#include <chrono>
#include <thread>
int main()
{
std::cout << "waiter" << std::endl;
std::chrono::milliseconds dura( 1000 );
std::this_thread::sleep_for( dura );
std::cout << "Waited 1000 ms\n";
}
C++11线程使用总结的更多相关文章
- c++11 线程:让你的多线程任务更轻松
介绍 本文旨在帮助有经验的Win32程序员来了解c++ 11线程库及同步对象 和 Win32线程及同步对象之间的区别和相似之处. 在Win32中,所有的同步对象句柄(HANDLE)是全局句柄.它们 ...
- c++11 线程的互斥量
c++11 线程的互斥量 为什么需要互斥量 在多任务操作系统中,同时运行的多个任务可能都需要使用同一种资源.这个过程有点类似于,公司部门里,我在使用着打印机打印东西的同时(还没有打印完),别人刚好也在 ...
- 托管C++线程锁实现 c++11线程池
托管C++线程锁实现 最近由于工作需要,开始写托管C++,由于C++11中的mutex,和future等类,托管C++不让调用(报错),所以自己实现了托管C++的线程锁. 该类可确保当一个线程位于 ...
- 简单的C++11线程池实现
线程池的C++11简单实现,源代码来自Github上作者progschj,地址为:A simple C++11 Thread Pool implementation,具体博客可以参见Jakob's D ...
- C++ 11 线程的同步与互斥
这次写的线程的同步与互斥,不依赖于任何系统,完全使用了C++11标准的新特性来写的,就连线程函数都用了C++11标准的lambda表达式. /* * thread_test.cpp * * Copyr ...
- c++11 线程池学习笔记 (一) 任务队列
学习内容来自一下地址 http://www.cnblogs.com/qicosmos/p/4772486.html github https://github.com/qicosmos/cosmos ...
- C++11线程池的实现
什么是线程池 处理大量并发任务,一个请求一个线程来处理请求任务,大量的线程创建和销毁将过多的消耗系统资源,还增加了线程上下文切换开销. 线程池通过在系统中预先创建一定数量的线程,当任务请求到来时从线程 ...
- c++11线程池实现
咳咳.c++11 增加了线程库,从此告别了标准库不支持并发的历史. 然而 c++ 对于多线程的支持还是比較低级,略微高级一点的使用方法都须要自己去实现,譬如线程池.信号量等. 线程池(thread p ...
- python学习笔记11 ----线程、进程、协程
进程.线程.协程的概念 进程和线程是操作系统中两个很重要的概念,对于一般的程序,可能有若干个进程,每一个进程有若干个同时执行的线程.进程是资源管理的最小单位,线程是程序执行的最小单位(线程可共享同一进 ...
随机推荐
- Maven学习(八)-----Maven依赖机制
Maven依赖机制 在 Maven 依赖机制的帮助下自动下载所有必需的依赖库,并保持版本升级. 案例分析 让我们看一个案例研究,以了解它是如何工作的.假设你想使用 Log4j 作为项目的日志.这里你要 ...
- 提取验证码到winform上webbroswer和axwebbroswer
在网上只有webbroswer的代码,所以自己又修改了修改改成axwebbroswer的 public static class yanZhengMaHelp { //webbrowser验证码 pu ...
- MySQL数据库之安装,基本操作
一.基础部分 1.数据库是什么 之前所学,数据要永久保留,比如用户注册的用户信息,都是保存于文件,而文件只能存在于某一台机器上. 如果我们不考虑从文件中读取数据的效率问题,并且假设我们的程序所有的组件 ...
- Raft 一致性协议算法 《In search of an Understandable Consensus Algorithm (Extended Version)》
<In search of an Understandable Consensus Algorithm (Extended Version)> Raft是一种用于管理日志复制的一致性算 ...
- java.util.MissingResourceException: Can't find bundle for base name init, locale zh_CN问题的处理
一.问题描述 项目开发使用的是SSM框架,项目那个正常运行,开发一个新功能后,添加了一些配置文件,再重新运行项目抛出异常,找不到name为init的bean. 二.异常信息详细 六月 30, 2018 ...
- 在进行分布式框架搭建的过程中,出现问题advised by org.springframework.transaction.interceptor.TransactionInterceptor.invoke(org.aopalliance.intercept.MethodInvocation)?
今天在进行宜立方商城,进行文件配置的时间,遇到如下的问题,问题是:advised by org.springframework.transaction.interceptor.TransactionI ...
- AirSim的搭建和使用
由于自己使用设备拍摄的数据质量太差,所以决定使用AirSim这个框架来生成数据.之所以使用这个框架,是因为之前同事用其生成了一些有效数据. 当然,我是不可能把我搭建的步骤一一写出来的,一来是因为太麻烦 ...
- scrum立会报告+燃尽图(第三周第三次)
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2286 项目地址:https://coding.net/u/wuyy694 ...
- 王者荣耀交流协会 -- 第4次Scrum会议
Scrum master : 王磊 要求1 : 工作照片 照片由高远博同学拍摄 ,王露芝同学(外援)没有参加本次会议. 要求2 : 时间跨度:2017年10月16日 18:00 - 18:44 共计4 ...
- 20172305 2018-2019-1 《Java软件结构与数据结构》第六周学习总结
20172305 2018-2019-1 <Java软件结构与数据结构>第六周学习总结 教材学习内容总结 本周内容主要为书第十章内容: 树(一种非线性结构,其中的元素被组织成一个层次结构) ...