C++11多线程(3)
创建、等待多个线程
创建多个线程时,最好使用vector与join()函数结合使用
#include <iostream>
#include <thread>
#include <vector>
using namespace std;
void print()
{
cout << "hello world" << endl;
}
int main()
{
vector<thread> threadVec;
for (int i = 0; i < 10; i++)
{
threadVec.push_back(thread(print));
}
for (vector<thread>::iterator it = threadVec.begin(); it != threadVec.end(); ++it)
{
it->join();
}
system("Pause");
return 0;
}
二、共享数据
1、只读数据
#include <iostream>
#include <thread>
#include <vector>
using namespace std;
vector<int> g_v = { 1, 2, 3 }; //共享数据,只读
void print()
{
cout << "id为 " << this_thread::get_id() << "的线程 打印g_v的值 " << g_v[0] << g_v[1] << g_v[2] << endl;
}
int main()
{
vector<thread> threadVec;
for (int i = 0; i < 10; i++)
{
threadVec.push_back(thread(print));
}
for (vector<thread>::iterator it = threadVec.begin(); it != threadVec.end(); ++it)
{
it->join();
}
system("Pause");
return 0;
}
共享数据是只读的情况下不会出现错误,所有的线程都能够按序打印1,2,3.所以共享数据只是可读数据时不必做特殊处理;
2、有读有写
#include <iostream>
#include <thread>
#include <vector>
#include <list>
using namespace std;
class A
{
public:
void inMsgRecQueue()
{
for (int i = 0; i < 100000; i++)
{
cout << "inMsgRecQueue执行" << endl;
msgRecvQueue.push_back(i);
}
}
void outMsgRecvQueue()
{
for (int i = 0; i < 100000; i++)
{
if (!msgRecvQueue.empty())
{
int command = msgRecvQueue.front();
msgRecvQueue.pop_front();
}
else
{
cout << "outMsgRecvQueue()执行,但是为空" << endl;
}
}
}
private:
list<int> msgRecvQueue;
};
int main()
{
A a;
thread myOutThread = thread(&A::outMsgRecvQueue, &a);
thread myInThread = thread(&A::inMsgRecQueue, &a);
myInThread.join();
myOutThread.join();
system("Pause");
return 0;
}
程序运行过程中会出现错误,有读有写造成的,所以要进行特殊处理,具体代码如下所示:
#include <iostream>
#include <thread>
#include <vector>
#include <list>
#include <mutex>
using namespace std;
class A
{
public:
void inMsgRecQueue()
{
mutexs.lock();
for (int i = 0; i < 100000; i++)
{
cout << "inMsgRecQueue执行" << endl;
msgRecvQueue.push_back(i);
}
mutexs.unlock();
}
void outMsgRecvQueue()
{
mutexs.lock();
for (int i = 0; i < 100000; i++)
{
if (!msgRecvQueue.empty())
{
int command = msgRecvQueue.front();
msgRecvQueue.pop_front();
}
else
{
cout << "outMsgRecvQueue()执行,但是为空" << endl;
}
}
mutexs.unlock();
}
private:
list<int> msgRecvQueue;
mutex mutexs;
};
int main()
{
A a;
thread myOutThread = thread(&A::outMsgRecvQueue, &a);
thread myInThread = thread(&A::inMsgRecQueue, &a);
myInThread.join();
myOutThread.join();
system("Pause");
return 0;
}
加上互斥量mutex后就可以进行安全访问了,必须包含头文件#include <mutex> 有两个重要的函数lock()和unlock(),对要访问的共享区加锁,解锁。在程序中lock()与unlock()必须成对使用,否则就会出现错误,这样在程序中比较容易发生错误。为了防止这种情况的发生,可以使用lock_guard()来代替之前的lock()与unlock()函数。lock_guard()是一个模板类函数,该函数在创建对象的时候调用lock()函数,在析构对象的时候调用unlock()函数,所以一定要注意该函数的作用域,在适当的范围内加大括号,在作用块的结束点析构对象。具体使用如下:
#include <iostream>
#include <thread>
#include <vector>
#include <list>
#include <mutex>
using namespace std;
class A
{
public:
void inMsgRecQueue()
{
for (int i = 0; i < 100000; i++)
{
lock_guard<mutex> guard(mutexs); //创建,但是一定注意作用域
cout << "inMsgRecQueue执行" << endl;
msgRecvQueue.push_back(i);
}
}
void outMsgRecvQueue()
{
for (int i = 0; i < 100000; i++)
{
lock_guard<mutex> guard(mutexs);
if (!msgRecvQueue.empty())
{
int command = msgRecvQueue.front();
msgRecvQueue.pop_front();
}
else
{
cout << "outMsgRecvQueue()执行,但是为空" << endl;
}
}
}
private:
list<int> msgRecvQueue;
mutex mutexs; //互斥量对象
};
int main()
{
A a;
thread myOutThread = thread(&A::outMsgRecvQueue, &a); //创建成员函数线程
thread myInThread = thread(&A::inMsgRecQueue, &a); //创建成员函数线程
myInThread.join();
myOutThread.join();
system("Pause");
return 0;
}