并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。所以无论从微观还是从宏观来看,二者都是一起执行的。
C++11的标准库中提供了多线程库,使用时需要#include <thread>
头文件
1、线程的声明
//声明一个线程,名字是T,name是实现这个线程的函数名字 thread T(name); //调用一个线程 T.join(); //声明多个线程 thread T[3]; for(int i=0;i<3;i++) { T[i]=thread(name); } //调用多个线程 for(int i=0;i<3;i++) { T[i].join() }
2、传参
//声明一个线程 thread T(name,int x);
3、函数join()和detach()的区别
join()和detach()函数都是用来决定线程的运行方式。当使用join方式时,会阻塞当前代码,等待新线程完成退出后,才会继续向下执行主线程;
而使用detach方式则不会对当前代码造成影响,当前代码继续向下执行,创建的新线程同时并发执行.
举个例子,执行下面代码
#include<iostream> #include<thread> using namespace std; void thread2() { for (int i = 0; i < 4; i++) cout << "thread1" << endl; }//抢占式,线程1和线程2都在抢占cout这个资源 int main() { //声明一个线程 thread T(thread2); //启动线程的两种方法 //T.detach(); T.join(); for (int i = 0; i < 4; i++) cout << "thread2" << endl; system("pause"); return 0; }
使用T.join()时输出如下 使用T.detach()时输出如下
多线程可能是并发也可能是并行,但是在使用多线程的时候,要注意资源的互斥使用,比如上面的T.detach()方式,Thread1和Thread2都在争抢资源cout的使用,所以在输出的时候的会有点乱,
T.join()方式也一样,只不过上面的代码只有Thread1在运行,没有其它线程抢占cout的资源,所以看起来是有序的输出
上面的cout我们叫做临界资源,它一次只能供一个进程使用,为了实现让输出有序( 资源的互斥使用 ),我们要给互斥资源加锁
4、互斥锁的使用(mutex)
互斥锁可以实现资源的互斥使用,头文件是#include<mutex>
//声明一个锁 mutex m; //加锁 m.lock(); /* *临 *界 *区 */ //解锁 m.unlock();
5、临界资源和临界区
临界资源:
多道程序系统中存在许多进程,它们共享各种资源,然而有很多资源一次只能供一个进程使用。一次仅允许一个进程使用的资源称为临界资源。许多物理设备都属于临界资源,如输入机、打印机、磁带机等。
临界区:
每个进程中访问临界资源的那段代码称为临界区。显然,若能保证诸进程互斥地进入自己的临界区,便可实现诸进程对临界资源的互斥访问。为此,每个进程在进入临界区之前,应先对欲访问的临界资源进行检查,看它是否正被访问。如果此刻该临界资源未被访问,进程便可进入临界区对该资源进行访问,并设置它正被访问的标志;如果此刻该临界资源正被某进程访问,则本进程不能进入临界区。
#include<iostream> #include<thread> #include<mutex>//互斥锁 using namespace std; mutex m; void thread2(int index) { for (int i = 0; i < 10; i++) { m.lock(); cout << index << " thread1 " << i << endl; m.unlock(); } }//抢占式,线程1和线程2都在抢占cout这个资源 int main() { //声明一个线程 thread T[4]; for (int i = 0; i < 4; i++) { T[i] = thread(thread2, i); } for (int i = 0; i < 4; i++) T[i].join(); for (int i = 0; i < 4; i++) cout << "thread2" << endl; system("pause"); return 0; }