线程的多种创建方式
C++线程创建的过程 – 普通函数的方式:
2.1 包含头文件 #include
2.2 创建线程:调用thread 类去创建一个线程对象
注意点:创建一个线程,不做处理,会调用abort函数终止程序
2.3 join函数 加入、汇合线程到主线程,阻塞主线程;等待子线程执行结束,
才会回到主线程
注意:一个线程只能join()一次,join()多次会引发中断
2.4 detach(); 函数分离,打破依赖关系;把子线程驻留后台。 注意与join()的区别;
当线程detach()后,就不能再join()了。
2.5 joinable()判断当前线程是否可以做join或者detach过程,可以返回true,否则false
其他创建线程的方法:
1、普通函数的方式,上面介绍过了
2、通过类和对象创建线程
3、Lambda表达式创建线程
4、带参的方式创建线程
5、带智能指针的方式创建线程
通过类的的成员函数创建进程
普通函数的方式
#include<iostream>
#include<thread>
#include<windows.h>
using namespace std;
//线程处理函数
void print(){
Sleep(5000); //让子线程休眠5000毫秒= 5秒钟
cout<<”子线程运行...”<<endl;
}
//创建第二个子线程
void print2() {
Sleep(5000); //此时子线程2也会休眠5秒
cout << "子线程2运行..." << endl;
}
int main(){
//创建线程
thread t1(print);
thread t2(print2); //创建子线程2
t1.join(); //阻塞;也就是说子线程没有运行结束,主线程是不会打印的
t2.join();
/*
此时程序一共休眠5S
output: 子线程1运行... 子线程2运行...
主线程运行...
*/
t1.join(); //阻塞; 也就是说子线程没有打印完,主线程是不会打印的
cout<<”主线程运行...”<<endl;
return 0;
}
以类的成员构造线程
#include<iostream>
#include<thread>
using namespace std;
class MM {
public:
void print(int& num) {
num = 10001;
cout << "子线程..." << this_thread::get_id() << endl;
}
};
int main() {
MM mm;
int num = 1001;
//需要告诉 是哪个对象
thread t1(&MM::print,mm,ref(num));
t1.join();
cout << "主线程..." << this_thread::get_id() << endl;
system("pause");
return 0;
}
以智能指针为参数创建
//#include<iostream>
//#include<thread>
//using namespace std;
/*
以智能指针为参数的线程处理函数
*/
void print(unique_ptr<int> ptr) {
cout << "子线程:" << ptr.get() << endl; //输出智能指针的地址
cout << this_thread::get_id() << endl;//获取线程id
}
int main() {
unique_ptr<int> ptr(new int(1000));
cout << "主线程..." << ptr.get() << endl; //使用ptr.get()获取; 此时输出的是智能指针的地址
thread t1(print,move(ptr)); //注意:此时需要用move
t1.join(); //调用子线程;输出智能指针的地址;此时和上面主线程输出的结果是一样的
cout << "主线程..." << ptr.get() << endl; //此时输出00000000 ;因为move的原因
cout << this_thread::get_id() << endl;//获取线程id
system("pause");
return 0;
}
带参的方式创建
#include<iostream>
#include<thread>
using namespace std;
/*
带参引用创建线程
*/
void printInfo(int& num) {
num++;
cout << "子线程\t" << num << endl;
}
int main() {
int num = 0;
//std::ref 用于包装引用传递值
thread t1(printInfo,std::ref(num));
t1.join(); // 将子线程加入到主线程
cout << "主线程..." << num << endl;
system("pause");
return 0;
}
多线程数据同步问题
#include<iostream>
#include<thread>
#include<mutex>
#include<list> //作为共享内存
using namespace std;
mutex mtx; //设置互斥量
class SeaKing{
public:
void makeFriend(list<int> &mm) {
lock_guard<std::mutex> mtx_locker(mtx); //mtx_locker(mtx)用于自动锁定解锁
for (int i = 0; i < 10; i++) {
mm.push_back(i);
cout << "增加一位女朋友:" << i << endl;
}
}
void breakUp(list<int> &mm) {
lock_guard<std::mutex> mtx_locker(mtx);
for (int j = 0; j < 10;j++) {
if (!mm.empty()) {
mm.pop_front();
cout << "分手一位女朋友:" << mm.front() << endl;
}
else {
cout << "都分手了" << endl;
}
}
}
protected:
list<int> mm;
};
int main() {
list<int> mm;
SeaKing fx;
thread t1(&SeaKing::makeFriend,fx,ref(mm));
thread t2(&SeaKing::breakUp,fx,ref(mm));
t1.join();
t2.join();
system("pause");
return 0;
}
利用互斥量解决并发问题
#include<iostream>
#include<thread>
#include<windows.h>
#include<mutex>
using namespace std;
/*
实现创建多线程
*/
void Fun_1(); //声明分支线程函数Fun_1()
void Fun_2(); //声明分支线程函数Fun_2()
unsigned int counter = 0; //定义变量counter,通过变量counter的变化来观察线程同步情况
std::mutex mtx; //定义mutex类的对象mtx构造互斥元,互斥占有一个变量,一段时间内仅一个线程可以访问
int main()
{
std::thread thrd_1(Fun_1); //创建线程thrd_1,thrd_1调用函数Fun_1
std::thread thrd_2(Fun_2); //创建线程thrd_2,thrd_2调用函数Fun_2
thrd_1.join(); //join()函数启动子线程而阻塞主线程,子线程会按照开启的先后顺序同步运行,
//当子线程运行结束后,才会继续运行主线程
thrd_2.join(); //启动线程thrd_2,并且阻塞主线程,等到线程thrd_2运行结束后,再继续运行主线程;
cout << "counter= " << counter << endl;
system("pause");
return 0;
}
void Fun_1()
{
while (true)
{
/*std::lock_guard类模板,用于自动锁定解锁,直到对象作用域结束。在 lock_guard 对象构造时,
传入的mutex对象 mtx 会被当前线程锁住。在lock_guard 对象被析构时,它所管理的mutex对象mtx会自动解锁*/
std::lock_guard<std::mutex> mtx_locker(mtx);
counter++;
if (counter < 5)
cout << "Function 1 counting ! counter=" << counter << endl;
else
break;
}
}
void Fun_2()
{
while (true)
{
/*std::lock_guard类模板,用于自动锁定解锁,直到对象作用域结束。在 lock_guard 对象构造时,
传入的mutex对象 mtx 会被当前线程锁住。在lock_guard 对象被析构时,它所管理的mutex对象mtx会自动解锁*/
std::lock_guard<std::mutex> mtx_locker(mtx);
counter++;
if (counter < 5)
cout << "Function 2 counting ! counter=" << counter << endl;
else
break;
}
}
std::lock_guard类模板,用于自动锁定解锁,直到对象作用域结束。在 lock_guard 对象构造时,传入的mutex对象 mtx 会被当前线程锁住。在lock_guard 对象被析构时,它所管理的mutex对象mtx会自动解锁;