1.C++11的标准库中的多线程库 #include
2.创建线程的格式 : 关键字thread 线程名(入口函数,入口函数的参数);
若入口函数参数比较多,按照顺序往后写,用英文逗号隔开。
3.子线程开始运行的两张方式:
例如:
#include
#include
#include
using namespace std;
void fun(int a)
{
cout << "子线程id为" << this_thread::get_id() << endl;
cout << "子线程睡眠5秒" << endl;
Sleep(5000);
}
int main()
{
int a = 10;
thread mythread(fun, 10);
cout << "主线程中的子线程id:" << mythread.get_id() << endl;
cout << "子线程加入:" << endl;
mythread.join();//主线程被阻塞直至子线程执行结束
//mythread.detach();//主线程子线程分别执行
cout << "子线程结束,返回主线程"<< endl;
return 0;
}
1.c++中互斥量是一个类,我们可以理解成是一把锁,在一些需要互斥使用的临界区(代码段)加上锁,锁住的代码区域要适中,太少起步到保护效果,太多会影响运行效率;
2.互斥量的头文件 #include
3.互斥量的创建 mutex m; 这个m是创建的类对象,mutex为类名;
4.lock()和unlock()要成对使用;
#include
#include
#include
#include
using namespace std;
mutex m;
int a = 1;
void fun1()
{
m.lock();
cout << "thr1拿到锁:" << endl;
cout << "原参数值" << a << endl;
cout << "现参数值" << ++a << endl;
m.unlock();
}
void fun2()
{
m.lock();
cout << "thr2拿到锁:" << endl;
cout << "原参数值" << a << endl;
cout << "现参数值" << --a << endl;
m.unlock();
}
int main()
{
thread thr1(fun1);
thread thr2(fun2);
//下面两个线程同时加入,但是执行顺序可能thr1在前,也可能thr2在前
//所以执行结果也有多种
//thr1拿到锁:
//原参数值1
//现参数值2
//thr2拿到锁:
//原参数值2
//现参数值1
//或
//thr2拿到锁:
//原参数值1
//现参数值0
//thr1拿到锁:
//原参数值0
//现参数值1
thr1.join();
thr2.join();
return 0;
}
为避免lock()之后忘记unlock(),造成临界区一直被锁,产生了类似于智能指针的两种方式
1.原理:构造函数中lock(),析构函数中unlouck();
2.可以通过使用{}来调整lock()的作用域范围,让互斥量m在合适的地方被解锁
3.使用lock_guard后不能手动lock()与手动unlock();如果lock_guard加了adopt_lock参数,表示构造函数中不再加锁,需要提前手动加锁。用std::adopt_lock的前提是,自己需要先把mutex lock上;
例如:m.lock();//手动锁定,m为mutex的类对象
lock_guard
4. lock_guard不可以复制也不可以转移(move)
#include
#include
#include
#include
using namespace std;
mutex m;
int a = 1;
void fun1()
{
lock_guard lockg1(m);
cout << "thr1拿到锁:" << endl;
cout << "原参数值" << a << endl;
cout << "现参数值" << ++a << endl;
}
void fun2()
{
m.lock();//先手动锁定,才能再使用unique_lock的adopt_lock参数
lock_guard lockg2(m, adopt_lock);
cout << "thr2拿到锁:" << endl;
cout << "原参数值" << a << endl;
cout << "现参数值" << --a << endl;
}
int main()
{
thread thr1(fun1);
thread thr2(fun2);
//下面两个线程同时加入,但是执行顺序可能thr1在前,也可能thr2在前
//所以执行结果也有多种
//thr1拿到锁:
//原参数值1
//现参数值2
//thr2拿到锁:
//原参数值2
//现参数值1
//或
//thr2拿到锁:
//原参数值1
//现参数值0
//thr1拿到锁:
//原参数值0
//现参数值1
thr1.join();
thr2.join();
return 0;
}
1.于功能上unique_lock类似于lock_guard,但是unique_lock的功能更强大一些,用法上也更灵活一些,但是比lock_guard要慢一些,内存占用多一些;
2.与lock_guard不同的是,使用unique_lock后可以手动lock()与手动unlock();
3.unique_lock的参数有adopt_lock、try_to_lock、defer_lock
4. unique_lock的成员函数 lock()、unlock()、try_lock()、release()
lock():加锁
lunlock():解锁
try_lock():尝试给互斥量加锁,如果拿不到锁,返回false,如果拿到了锁,返回true,这个函数是不阻塞的
release():返回它所管理的mutex对象指针,并释放所有权;也就是说,这个unique_lock和mutex不再有关系。
5. unique_lock不可以复制,可以把所有权转移给其他锁(move)
例如:
unique_lock
unique_lock
#include
#include
#include
#include
using namespace std;
mutex m;
int a = 1;
void fun1()
{
unique_lock lockg1(m, defer_lock);//初始化一个没有加锁的mutex
lockg1.lock();//unique_lock加锁,不是m.lock();
cout << "fun1拿到m锁:" << endl;
cout << "原参数值" << a << endl;
cout << "现参数值" << ++a << endl;
//lockg1.unlock();
}
void fun2()
{
unique_lock lockg2(m, try_to_lock);//尝试拿锁,只尝试一次,如果没拿到就返回,不会导致本线程一直阻塞在lock这里。
if (lockg2.owns_lock())
{
cout << "fun2拿到m锁:" << endl;
cout << "原参数值" << a << endl;
cout << "现参数值" << --a << endl;
}
else
{
cout << "fun2没有拿到m锁" << endl;
}
}
int main()
{
thread thr1(fun1);
thread thr2(fun2);
//下面两个线程同时加入,但是执行顺序可能thr1在前,也可能thr2在前
//所以执行结果也有多种:
/*fun2拿到m锁:
原参数值1
现参数值0
fun1拿到m锁:
原参数值0
现参数值1*/
//或
//fun2没有拿到m锁fun1拿到m锁:
//原参数值
//1
//现参数值2
//或
//fun1拿到m锁:fun2没有拿到m锁
//原参数值1
//现参数值2
thr2.join();
thr1.join();
return 0;
}