C++11多线程基本使用
来源:互联网 发布:网络对唱歌曲大全 编辑:程序博客网 时间:2024/06/13 01:22
原贴:http://blog.csdn.net/wrx1721267632/article/details/52197849
感觉代码挺成熟的,不像很多博客都是烂大街的基础知识。
C++11增加了线程及线程相关的累,很方便的支持了并发编程,使得编写的多线程程序的可移植性得到了很大的提高.
线程的创建
用std::thread 创建线程非常的简单,只需要提供线程函数或者函数对象即可,并可以同时指定线程的参数:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
线程函数将会运行于线程对象t中,join函数将会阻塞线程,直到线程函数执行结束,如果线程函数有返回值,返回值将被忽略.
detach可以将线程与线程对象分离,让线程作为后台线程执行,当前线程也不会阻塞了.但是detach之后就无法在和线程发生联系了.如果线程执行函数使用了临时变量可能会出现问,线程调用了detach在后台运行,临时变量可能已经销毁,那么线程会访问已经被销毁的变量.join能保证.
虽然这种方式创建线程很方便,但是std::thread 出了作用域后将会析构,这个时候线程函数还没执行完则会发生错误.
线程不可以复制但是可以移动.但是线程移动后,线程对象将不再代表任何线程了:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
互斥量
互斥量是一种同步原语,是一种线程同步的手段,用来保护多线程同时访问的共享数据.
std::mutex: 独占的互斥量,不能递归使用.
std::timed_mutex: 带超时的独占互斥量,不能递归使用.
std::recursive_mutex: 递归互斥量,不带超时功能.
std::recursive_timed_mutex: 带超时的递归互斥量.
这些互斥量的基本接口十分相近,都是通过lock()来阻塞线程,直到获得互斥量的所有权为止.在线程或的互斥量并完成任务后,就必须使用unlock()来解除对互斥量的占用,lock和unlock必须成对出现.try_lock()尝试锁定互斥量,成功返回true,失败返回false,他是非阻塞的.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
lock_guard用到了RAII的技术,这种技术在类的构造函数中分配资源,在析构函数中释放资源,保证资源在出了作用域之后就释放.
std::recursive_mutex递归锁允许同一个线程多次获得互斥量.但是尽量不要使用递归锁:
- 需要用到递归锁定的多线程互斥处理往往本身就是可以简化的,允许递归互很容易放纵复杂逻辑的产生,从而导致一些多线程同步引起的晦涩问题.
- 递归锁比起非递归锁,效率会低.
- 递归锁虽然允许同一个线程多次获得同一互斥量,但是可重复获得的最大次数并未具体说明,一旦超过一定次数就会抛出异常.
带超时的互斥量在获取锁的时候增加了超时等待功能,因为有时不知道获取锁需要多久,为了不至于一直等待获取互斥量,就设置一个等待超时时间,在超时后还可以做其他的的事情.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
条件变量
条件变量阻塞一个或多个线程,直到收到另外一个线程发来的通知或者超时,才会唤醒当前阻塞的进程,条件变量需要和互斥量配合使用.
C++11提供了两种条件变量
- std::condition_variable,配合std::unique_lock进行wait操作
- std::condition_variable_any,和任意带有lock,unlock的mutex进行搭配使用,比较灵活但效率略低。
条件变量的使用过程如下:
- 拥有条件变量的线程获取互斥锁
- 循环检查某个条件,如果条件不满足,则阻塞直到条件满足,如果条件满足,则向下执行.
- 某个线程满足条件执行完之后调用notify_one或notify_all唤醒一个或者所有的等待线程.
eg:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
原子变量
- C++11提供了一个原子类型
std::atomic<T>
,可以使用任意类型作为模板参数,C++11内置了整性的原子变量,使用原子变量就不需要使用互斥量来保护改变量了.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
call_once/once_flag
- 为了保证在多线程环境中某个函数仅被调用一次,例如,需要初始化某个对象,而这个对象智能被初始化一次的话,就可以使用std::call_once来保证函数在多线程环境下只调用一次.
- c++11 多线程 -- 基本使用
- C++11多线程基本使用
- C++11多线程基本使用
- c++11 多线程 -- 基本使用
- IOS多线程基本使用
- 多线程:GCD 基本使用
- Java多线程-基本使用
- 多线程【概述+基本使用】
- C语言多线程-基本操作
- 多线程(一) 多线程介绍及基本使用
- Win32 多线程的基本使用
- 多线程的基本使用实例
- 多线程 - 09.NSOperation基本使用
- 网络多线程-NSOperationQueue基本使用
- iOS多线程的基本使用
- 多线程:NSOperation 的基本使用
- 多线程:NSOperation 的基本使用
- Android 多线程的基本使用
- JQuery:事件冒泡和阻止默认行为
- MySQL数据加密与解密
- SpringMVC源码总结(八)类型转换PropertyEditor的背后
- java程序中前台后中文编码的问题
- linux 内核宏定义:#define typecheck(type,x)
- C++11多线程基本使用
- 安装redis集群,时候安装ruby redis接口报错问题
- 网络爬虫二三事儿
- java逆转链表
- SpringMVC源码总结(九)HandlerMethodArgumentResolver介绍
- AndroidStudio 中的 Android plugin version与Gradle version、SDK Build Tools之间的关系
- Out of memory: kill process 6184 (XXX) score 166 or a child Killed process 6184 (XXX)
- 【Windows DOS】如何复制命令提示符窗口的内容?
- C语言经典书籍推荐