创建多个线程
vector<thread> g;
void myjob(int num){
cout<<num<<endl;
}
for(int i=1;i<=10;i++){
g.push_back(thread (myjob,i));
}
for(auto item=g.begin();item!=g.end();item++){
item->join();
}
线程执行的顺序是乱的 , 这与操作系统内部对线程的运行调度机制有关
数据共享问题
1 , 只读数据是安全稳定的 , 不需要特别什么处理手段 , 直接读就可以
2 , 有读有写 , 读的时候不能写 , 写的时候不能读
互斥量
互斥量是个类对象.理解成一把锁 , 多个线程尝试用lock( ) 成员函数来加锁 , 只有一个线程可以锁定成功(成功的标志是lock()函数返回 ) 如果没有锁成功 , 那么流程卡在lock() 这不断尝试去锁这把锁
用法 :
步骤:先
lock()
,操作共享数据 ,unlock()
lock()
和unlock()
成对使用
#include<mutex>
class A{
public:
void inmRQ(){
for(int i=1;i<=100000000;i++){
my_mutex.lock();
mRQ.push(i);
my_mutex.unlock();
cout<<"start"<<endl;
}
}
void outmRQtem(int &command){
my_mutex.lock();
if( !mRQ.empty() ){
command=mRQ.front();
mRQ.pop();
}
my_mutex.unlock();
}
void outmRQ(){
int command=0;
for(int i=1;i<=100000000;i++){
outmRQtem(command);
cout<<command<<endl;
}
cout<<"end"<<endl;
}
private:
std::queue<int> mRQ;
std::mutex my_mutex;//创建一个互斥量
};
int main(){
A a;
thread myout(&A::outmRQ,ref(a));
thread myin(&A::inmRQ,ref(a));
myin.join();
myout.join();
return 0;
}
std::lock_guard
std::lock_guard
类模板 可以直接取代lock()
和unlock()
: 用了lock_guard
之后 , 再不能使用lock()
与unlock()
void outmRQtem(int &command){
std::lock_guard<std::mutex> myguard(my_mutex);
//构造函数执行了lock(),析构函数执行了unlock()
//这个函数结束,生命周期结束自动调用析构函数
if( !mRQ.empty() ){
command=mRQ.front();
mRQ.pop();
}
}
{//加大括号,使lock_guard生命周期在大括号内
std::lock_guard<std::mutex> myguard(my_mutex);
if( !mRQ.empty() ){
command=mRQ.front();
mRQ.pop();
}
}
死锁
我有两把锁,金锁和银锁,两个线程A和B
(1) 线程A执行时,把金锁lock了 , 然后准备要去lock银锁时…
(2) 跳到了线程B ,这时线程B把银锁lock了 , 然后去lock金锁 , lock失败 ,于是就被停滞了
(3) 然后A继续lock银失败 , 也停滞了,这时死锁便产生了
死锁样例
#include<iostream>
#include<cstdio>
#include<thread>
#include<cstdlib>
#include<vector>
#include<list>
#include<queue>
#include<mutex>
using namespace std;
class A{
public:
void inmRQ(){
my_mutex2.lock();
for(int i=1;i<=100000000;i++){
my_mutex1.lock();
mRQ.push(i);
my_mutex1.unlock();
cout<<"start"<<endl;
}
my_mutex2.unlock();
}
void outmRQtem(int &command){
my_mutex1.lock();
if( !mRQ.empty() ){
my_mutex2.lock();
command=mRQ.front();
mRQ.pop();
my_mutex2.unlock();
}
my_mutex1.unlock();
}
void outmRQ(){
int command=0;
for(int i=1;i<=100000000;i++){
outmRQtem(command);
cout<<command<<endl;
}
cout<<"end"<<endl;
}
private:
std::queue<int> mRQ;
std::mutex my_mutex1;
std::mutex my_mutex2;
};
int main(){
A a;
thread myout(&A::outmRQ,ref(a));
thread myin(&A::inmRQ,ref(a));
myin.join();
myout.join();
return 0;
}
#include<iostream>
#include<cstdio>
#include<thread>
#include<cstdlib>
#include<vector>
#include<list>
#include<queue>
#include<mutex>
using namespace std;
class A{
public:
void inmRQ(){
lock_guard<std::mutex> myguard(my_mutex2);
for(int i=1;i<=100000000;i++){
lock_guard<std::mutex> myguard2(my_mutex1);
mRQ.push(i);
cout<<"start"<<endl;
}
}
void outmRQtem(int &command){
lock_guard<std::mutex> myguard2(my_mutex1);
if( !mRQ.empty() ){
lock_guard<std::mutex> myguard2(my_mutex2);
command=mRQ.front();
mRQ.pop();
}
}
void outmRQ(){
int command=0;
for(int i=1;i<=100000000;i++){
outmRQtem(command);
cout<<command<<endl;
}
cout<<"end"<<endl;
}
private:
std::queue<int> mRQ;
std::mutex my_mutex1;
std::mutex my_mutex2;
};
int main(){
A a;
thread myout(&A::outmRQ,ref(a));
thread myin(&A::inmRQ,ref(a));
myin.join();
myout.join();
return 0;
}