C++多线程
线程的概念
线程(thread)是计算机科学中的一个重要概念,它是进程(process)中的一个执行单元。简而言之,一个进程可以包含多个线程,每个线程可以独立执行不同的任务。
与进程相比,线程更轻量级,因为它们共享相同的内存空间和系统资源。这意味着在同一个进程中的线程可以更快地进行通信和数据共享,相比于不同进程之间的通信开销更小。
线程可以同时执行多个任务,使得程序能够更高效地利用多核处理器的并行能力。例如,在一个网络服务器应用程序中,可以使用多个线程来处理并发的客户端请求,从而提高服务器的响应速度。
线程之间可以通过共享内存进行通信,也可以使用同步机制(如互斥锁、条件变量等)来实现线程间的协调与同步。然而,由于多个线程共享同一份数据,因此在编写多线程程序时需要特别注意线程安全问题,以避免数据竞争和其他潜在的并发问题。
总结起来,线程是进程中的执行单元,它们能够同时执行多个任务,提高程序的性能和响应能力。
Thread
C++11中加入了头文件,此头文件主要声明了std::thread线程类。
线程涉及到操作系统的内容,如果学习了操作系统之后再来学习这部分的内容会更好一点。
创建进程
#include <thread>
#include<iostream>
using namespace std;
void Func1(){
cout << "Hello world" << endl;
}
int main(){
//在这里创建一个进程T1
thread T1(Func1);
return 0;
}
如果复制这样子的代码到VS2022中运行,会出现这样子的情况
原因:
这个线程是在main的进程里面的一个分支,到了main函数的结尾的,函数return返回了结束了,但是Func1这个进程却没有结束,因此会出现错误。
在多线程中,怎么理清楚每个线程之间的执行顺序是难点
在thread中有许多的成员函数:
-
**joinable:**检查线程是否可被join。检查thread对象是否标识一个活动(active)的可行性线程。缺省构造的thread对象、已经完成join的thread对象、已经detach的thread对象都不是joinable。
-
**join:**调用该函数会阻塞当前线程。阻塞调用者(caller)所在的线程直至被join的std::thread对象标识的线程执行结束
在调用join()成员函数的时候,他会先去判断joinable
如果在主进程中加入join函数,那么就当于是说,我先将当前的T1执行结束之后,在去执行主进程
保证了进程的执行顺序
#include <thread>
#include<iostream>
using namespace std;
void Func1() {
cout << "Hello world" << endl;
}
int main() {
//在这里创建一个进程T1
thread T1(Func1);
T1.join();
return 0;
}
在这里我重新创建了一个新的函数Func2
如果thread T2(Func2,"Hello Func2");
第一个相当于函数入口,第二个参数是传入函数入口的参数
如果不传入参数的话,程序也会报错
#include <thread>
#include<iostream>
using namespace std;
void Func1() {
cout << "Hello world" << endl;
}
void Func2(const char* str) {
cout << "Func2:" << str << endl;
}
int main() {
//在这里创建一个进程T1
thread T1(Func1);
thread T2(Func2,"Hello Func2");
T1.join();
T2.join();
return 0;
}
在这里我们又发现了一个问题
在代码中,我明明是有换行的啊,为什么在这里我的换行没有了呢?
这里理解的话:理解成,两个进程都抢着要执行,一个进程还没有完完全全的执行完毕,另外一个进程就开始执行了。因为多线程的不确定性,代码的执行顺序不一定是按照我们以为的那样子。
如果要解决的话,就是用加锁的操作,把两个进程之间完全的分开
mutex锁(互斥锁)
如果一个进程或者线程你保证没有别的与他竞争,那么你可以考虑不用加锁
对于子进程可能抢占共享资源的,我们都需要加锁的操作,防止对共享资源的抢占。
cout和cin这样的输入和输出端也是属于共享资源
在进入进程的时候lock,离开的时候unlock(释放)
#include <thread>
#include<iostream>
#include <mutex>
using namespace std;
mutex Func_mutex;//创建一个锁对象
void Func1() {
Func_mutex.lock();
cout << "Hello world" << endl;
Func_mutex.unlock();
}
void Func2(const char* str) {
Func_mutex.lock();
cout << "Func2:" << str << endl;
Func_mutex.unlock();
}
int main() {
//在这里创建一个进程T1
thread T1(Func1);
thread T2(Func2,"Hello Func2");
T1.join();
T2.join();
return 0;
}
可以看到输出的结果果然变了