C++11多线程:
1、多线程概念
![](https://img-blog.csdn.net/20180805102936455?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
C++11新增了对多线程的支持,提供了<atomic>、<mutex>和<thread>初步支持,但仍不完美。
![](https://img-blog.csdn.net/20180805103825668?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
使用并发的原因:关注点分离和性能。
不适用并发的情况:收益比不上成本,难以理解和维护。
C++98不承认多线程的存在,那就使用POSIX标准线程和Windows 多线程API,这会依赖于平台。
![](https://img-blog.csdn.net/20180805104454935?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
codeblocks中需配置支持C++11的选项才能支持C++11版的多线程。
#include <iostream>
#include <thread>
using namespace std;
void hello()
{
cout << "Hello Concurrent world\n";
}
int main()
{
thread t(hello);
t.join();
}
使用detach会让线程在后台运行,分离线程为守护线程。
向线程函数传递参数。
2、转移线程所有权
Boost并发编程:
1、Boost提供的并发编程库非常流行。
![](https://img-blog.csdn.net/2018080512035349?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/20180805120601452?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
thread库需要chrono库提供的时间概念来进行休眠。
互斥量mutex是一种用于线程同步的手段,一旦一个线程锁住了互斥量,那么其他线程必须等待它解锁互斥量后才能再访问共享资源。
![](https://img-blog.csdn.net/20180805125110360?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
互斥量都是boost::noncopyable:
![](https://img-blog.csdn.net/20180805125259315?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/20180805125533810?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/20180805125635391?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。
RAII 的一般做法是这样的:在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:
- 不需要显式地释放资源。
- 采用这种方式,对象所需的资源在其生命期内始终保持有效。
Linux下C++多线程:
Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linux下pthread的实现是通过系统调用clone()来实现的。clone()是Linux所特有的系统调用,它的使用方式类似fork。
1、线程基本操作
线程创建
函数原型:int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr,void *(*start_rtn)(void),void *restrict arg);
返回值:若是成功建立线程返回0,否则返回错误的编号。
形式参数:pthread_t *restrict tidp 要创建的线程的线程id指针,即,创建成功后,该指针指向的内存存放创建线程的id;const pthread_attr_t *restrict attr创建线程时的线程属性;void* (start_rtn)(void)返回值是void类型的指针函数;void *restrict arg start_rtn的形参。
·线程挂起:该函数的作用使得当前线程挂起,等待另一个线程返回才继续执行。也就是说当程序运行到这个地方时,程序会先停止,然后等线程id为thread的这个线程返回,然后程序才会断续执行。
函数原型:int pthread_join( pthread_t thread, void **value_ptr);
参数说明如下:thread等待退出线程的线程号;value_ptr退出线程的返回值。
·线程退出
函数原型:void pthread_exit(void *rval_ptr);
·获取当前线程id
函数原型:pthread_t pthread_self(void);
·互斥锁
创建pthread_mutex_init;销毁pthread_mutex_destroy;加锁pthread_mutex_lock;解锁pthread_mutex_unlock。
·条件锁
创建pthread_cond_init;销毁pthread_cond_destroy;触发pthread_cond_signal;广播pthread_cond_broadcast S;等待pthread_cond_wait
2、线程安全
![](https://img-blog.csdn.net/20180805115417505?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/20180805130557100?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/20180805151028688?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/20180805151223399?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/20180805151336785?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/20180805151505948?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/20180805151649644?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
要在多个线程中同时访问同一个shared_ptr,要加mutex保护。
![](https://img-blog.csdn.net/20180805152852131?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
3、线程同步
![](https://img-blog.csdn.net/20180805153700444?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
互斥器mutex:
![](https://img-blog.csdn.net/20180805153920575?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/2018080515401428?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
死锁排查,函数调用栈bt。
条件变量:
![](https://img-blog.csdn.net/20180805155058251?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/2018080515530295?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/20180805155415191?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
不要使用读写锁和信号量:
4、多线程服务器的使用场合
![](https://img-blog.csdn.net/20180805160340847?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/20180805160419674?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/20180805160559268?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![](https://img-blog.csdn.net/2018080516080350?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
BlockingQueue<T>是多线程编程的利器,
![](https://img-blog.csdn.net/20180805161019355?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
Linux下进程间通信的方式有:匿名或具名管道、POSIX消息队列、共享内存、信号、Socket等,同步原语有互斥量、信号量、条件变量、读写锁、文件锁等。进程间通信首选Socket。
![](https://img-blog.csdn.net/20180805162900599?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
5、I/O复用
Linux下I/O多路复用主要有select、poll和epoll。
select系统调用的用途是:在一段指定时间内监听用户感兴趣的文件描述上的可读、可写和异常等事件。
![](https://img-blog.csdn.net/20180805165619696?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5rYWlmYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)