并发与并行
网上看到一组生动形象描述并发与并行的图片:
并发
同时间只能处理一种操作
并行
同一时间可以处理多种操作
C++11多线程
每个C++程序均包含默认主线程main函数,通过thread创建新线程,可为thread对象附加回调,回调类型支持函数指针、函数对象、Lambda。
Hello World !
单线程
#include <iostream>
using namespace std;
int main()
{
cout<<"Hello World !"<<endl;
return 0;
}
多线程
#include <iostream>
#include <thread>
using namespace std;
void sayHi()
{
cout<<"Hello World !"<<endl;
}
int main()
{
thread* t = new thread(sayHi);
t->join();
delete t;
return 0;
}
#include <iostream>
#include <thread>
using namespace std;
struct MyStruct
{
void sayHi()
{
cout<<"Hello World !"<<endl;
}
}
int main()
{
MyStruct s;
thread* t = new thread(&MyStruct::sayHi, s);
t->join();
delete t;
return 0;
}
敲黑板——知识点
join():调用者将等待目标线程结束后继续运行。
detach():调用者与目标线程分离,调用者无需等待目标线程结束。
线程对象可移动不可复制
#include <iostream>
#include <thread>
using namespace std;
void f1();
void f2();
int main()
{
thread t1(f1);
//thread t2 = t1; //编译错误
thread t2 = move(t1); //此时t1中没有线程
t1 = thread(f2);
thread t3 = move(t2); //此时t2中没有线程
//t1 = move(t3); //程序终止,因为t1中已有线程在管理
return 0;
}
互斥锁
无互斥锁时:打印输出看心情,因为cout是共享资源~
#include <iostream>
#include <thread>
using namespace std;
void f1() {
for(int i = 0; i < 100; i++)
cout << i << endl;
}
int main()
{
thread t1(f1);
for(int i = 0; i > -100; i--)
cout << i << endl;
t1.join();
return 0;
}
有互斥锁时:
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
mutex mu;
void test(int i) {
mu.lock();
cout << i << endl;
mu.unlock();
}
void f1() {
for(int i = 0; i < 100; i++)
test(i);
}
int main()
{
thread t1(f1);
for(int i = 0; i > -100; i--)
test(i);
t1.join();
return 0;
}
BUT 如果lock()和unlock()之间发生异常,unlock()没机会执行时,会导致互斥锁一直处于锁住状态,会导致线程阻塞。
为解决此问题,引入RAII(Resource Acquisition Is Initialization 获取资源即初始化)技术。在类的构造函数中创建资源,析构函数中释放资源,这样即使发生异常,也能保证析构函数的执行。
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
mutex mu;
void test(int i) {
lock_guard<mutex> guard(mu);
cout << i << endl;
}
void f1() {
for(int i = 0; i < 100; i++)
test(i);
}
int main()
{
thread t1(f1);
for(int i = 0; i > -100; i--)
test(i);
t1.join();
return 0;
}
封装互斥锁保护数据
#include <iostream>
#include <thread>
#include <mutex>
#include <fstream>
using namespace std;
mutex mu;
class LogFile {
mutex m_mutex;
ofstream f;
public:
LogFile()
{
f.open("log.txt");
}
~LogFile()
{
f.close();
}
void test(int id)
{
std::lock_guard<std::mutex> guard(mu);
f << id << endl;
}
/*
// Never ever ever!!!不要返回数据,提供泄露数据的机会
ofstream& getStream()
{
return f;
}
*/
/*
// Never ever ever!!!不要传递数据,提供泄露数据的机会
void process(void fun(ostream&))
{
fun(f);
}
*/
};
void f1(LogFile& log) {
for(int i = 0; i < 100; i++)
log.test(i);
}
int main()
{
LogFile log;
thread t1(f1, ref(log));
for(int i = 0; i > -100; i--)
log.test(i);
t1.join();
return 0;
}
参考文档:https://segmentfault.com/a/1190000016171072