1 线程基础
1.1 并发、进程、线程的基本概念
- 并发:两个或者多个独立的活动同时进行,并发假象:单核CPU,上下文切换
- 进程:计算机调动计算机资源的最小单位,关于某一个数据集合上的一次运行活动
- 线程:线程是调度CPU的最小单元。也叫轻量级进程,在一个进程里可以创建多个线程,每个线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。
并发的实现:
- 多进程实现并发
- 主要解决的问题进程间通信的问题
- 一个电脑上:管道,文件,消息队列,内存共享
- 不同电脑通过SOCKET网络通信实现
- 单个进程,多线程实现并发
- 一个进程中的所有线程共享的内存空间,例如:全局变量,指针引用
1.2 线程的多种创建方式
1.2.1 普通函数创建
包含头文件
创建线程
- 创建一个线程,不做处理,会调用abort函数终止程序
- 一个线程只能join一次
join()函数加入,回合线程,阻塞主线程,等待子线程执行结束,才会回到主线中
detach()函数,分离,打破依赖关系,子线程执没执行完,我也不知道
joinable()判断当前线程是否可以做join或者detach过程,可以返回true,不可以返回false
#include<thread>
#include<iostream>
#include<windows.h>
using namespace std;
void print(){
Sleep(5000);
cout << "子线程运行..." << endl;
}
int main(){
//创建线程
thread test1(print);
test1.join(); //阻塞,等待子线程结束后,才向下运行
cout << "主线程。。。。" << endl;
if(test1.joinable()){
test1.join();
cout<<"可以"<<endl;
}else {
cout <<"子线程已经被处理"<<endl;
}
return 0;
}
1.2.2通过类和对象
#include <iostream>
#include <thread>
using namespace std;
class MM
{
public:
//类似仿函数,用类名模仿函数的行为
void operator()() {
cout << "子线程启动..." << endl;
}
};
int main() {
MM mm;
thread test1(mm);
test1.join();
thread test2((MM()));
test2.join();
cout << "主线程结束" << endl;
return 0;
}
1.2.3 Lambda表达式创建线程
#include <iostream>
#include <thread>
using namespace std;
int Max(int a, int b) {
return a > b ? a : b;
}
int main() {
//[] 捕获数据
//() 函数参数
// 是否存在异常
//-> 返回参数
//{} 函数体
int(*pMax)(int, int) = nullptr; //函数指针
pMax = [](int a, int b)->int {return a > b ? a : b; };
thread test1([] { cout << "子线程启动..." << endl; });
test1.join();
cout << "主线程结束" << endl;
return 0;
}
1.2.4 带参的方式创建线程
#include <iostream>
#include <thread>
using namespace std;
void printInfo(int & num) {
cout << "子线程\t" << num << endl;
}
int main() {
//std::ref 用于包装引用传递的值
int num = 1;
thread test1(printInfo, std::ref(num));
test1.join();
cout << "主线程结束" << endl;
return 0;
}
1.2.5 带智能指针创建线程
#include <iostream>
#include <thread>
using namespace std;
void printInfo(unique_ptr<int> ptr) {
cout << "子线程\t" << ptr.get() << "\t";
cout << this_thread::get_id() << endl;
}
int main() {
//std::ref 用于包装引用传递的值
unique_ptr<int> ptr(new int(1000)); //好处就是不需要手动的释放
//move 移动语义
thread test1(printInfo, move(ptr));
test1.join();
cout << "主线程结束\t" << ptr.get() << "\t";
cout << this_thread::get_id() << endl;
// 这里数据移动到了子线程,主线程就不在
cout << "*******************************************" << endl;
return 0;
}
1.2.6 通过类的成员函数创建线程
#include <iostream>
#include <thread>
using namespace std;
class MM {
public:
void print(int & num) {
num = 1001;
cout <<"子线程\t"<< this_thread::get_id() << endl;
}
};
int main() {
MM mm;
int num = 1007;
thread test1(&MM::print,mm, ref(num));
test1.join();
cout << "主线程结束\t" << "\t";
cout << this_thread::get_id() << endl;
// 这里数据移动到了子线程,主线程就不在
cout << "*******************************************" << endl;
return 0;
}
1.2.7 线程访问共享数据出现的冲突
多个线程共享数据的时候,出现冲突,这里就需要线程锁
基础就到这里了