创建多个线程
#include<iostream>
#include<thread>
#include<vector>
using namespace std;
void print(int i)
{
cout<<"子线程"<<i<<"开始"<<endl;
cout<<"子线程"<<i<<"结束"<<endl;
}
int main()
{
vector<thread>myThreads;
for(int i=0; i<10; i++)
myThreads.push_back(thread(print,i));
for(auto iter = myThreads.begin(); iter!=myThreads.end(); ++iter)
{
iter->join();
}
cout<<"主线程结束"<<endl;
return 0;
}
由下图可以看出多个线程的执行是不确定的,和操作系统对线程的调度有关。
互斥量 多线程保护共享数据
问题:一个线程往队列内插入数据,另一个线程往队列内取数据,在没有保护措施的情况下,此时的程序是不稳定的。
措施:采取使用互斥的方法保护共享数据
#include<iostream>
#include<thread>
#include<vector>
#include<list>
using namespace std;
class A
{
public:
void input()
{
for(int i=0;i<100000;i++)
{
cout<<"插入元素"<<i<<endl;
msg.push_back(i);
}
}
void output()
{
for(int i=0;i<100000;i++)
{
if(msg.empty())
{
cout<<"队列为空"<<endl;
}
else
{
int command = msg.front();
cout<<"取出元素"<<command<<endl;
msg.pop_front();
}
}
}
private:
list<int>msg;
};
int main()
{
A myobja;
thread insert_thread(&A::input,&myobja);
thread pop_thread(&A::output,&myobja);
insert_thread.join();
pop_thread.join();
cout<< "线程执行完成" <<endl;
return 0;
}
互斥量的用法
1.lock(),unlook()
先lock、共享数据、unlock
成对使用
void input()
{
for(int i=0;i<100000;i++)
{
my_mutex.lock(); //加锁
cout<<"插入元素"<<i<<endl;
msg.push_back(i);
my_mutex.unlock();//解锁
}
}
void output()
{
for(int i=0;i<100000;i++)
{
my_mutex.lock(); //加锁
if(msg.empty())
{
cout<<"队列为空"<<endl;
}
else
{
int command = msg.front();
cout<<"取出元素"<<command<<endl;
msg.pop_front();
}
my_mutex.unlock();//解锁
}
}
2.模板类std::lock_guard
可取代lock、unlock()
void output()
{
lock_guard<mutex>guard(my_mutex);
/*
构造函数里调用look()
析构函数里调用unlook()
缺点:不够灵活
*/
for(int i=0;i<100000;i++)
{
if(msg.empty())
cout<<"队列为空"<<endl;
else
{
int command = msg.front();
cout<<"取出元素"<<command<<endl;
msg.pop_front();
}
}
}
死琐
A等B,B等A或者有一个互等的循环
产生死锁
#include<iostream>
#include<thread>
#include<vector>
#include<list>
#include<mutex>
using namespace std;
class A
{
public:
void input()
{
my_mutex1.lock();
for(int i=0;i<1000000;i++)
i=i;
/*
其他程序
*/
my_mutex2.lock();
my_mutex1.unlock();
my_mutex2.unlock();
}
void output()
{
my_mutex2.lock();
for(int i=0;i<1000000;i++)
i=i;
/*
其他程序
*/
my_mutex1.lock();
my_mutex1.unlock();
my_mutex2.unlock();
}
private:
list<int>msg;
mutex my_mutex1; ///互斥量1
mutex my_mutex2; ///互斥量2
};
int main()
{
A myobja;
thread insert_thread(&A::input,&myobja);
thread pop_thread(&A::output,&myobja);
insert_thread.join();
pop_thread.join();
cout<< "线程执行完成" <<endl;
return 0;
}
上面程序进程一把一号锁锁住等待二号锁
上面程序进程二把二号锁锁住等待一号锁
产生互相等待
解决方案,保持调用顺序一致理论上不会死锁
std::lock()
一次锁住两个或以上的互斥量
如果失败则一个都不锁,要么全都锁住。从而避免死琐的问题
std::lock_guard的std::adopt_lock参数
lock_guard (mutex_type& m, adopt_lock_t tag);
lock_guard 对象管理 Mutex 对象 m,与 locking 初始化(1) 不同的是, Mutex 对象 m 已被当前线程锁住。
lock_guard<mutex>guard(my_mutex1,std::adopt_lock_t);