C++多线程编程(使用C++11后的thread库)——使用thread类进行多线程编程 学习笔记

it2024-02-21  73

参考以下博文: [c++11]多线程编程(一)——初识 [c++11]多线程编程(二)——理解线程类的构造函数 [c++11]多线程编程(三)——竞争条件与互斥锁 [c++11]多线程编程(四)——死锁(Dead Lock) [c++11]多线程编程(五)——unique_lock [c++11]多线程编程(六)——条件变量(Condition Variable) 深入学习c+±-多线程编程(三)thread的两种死法

以下代码笔记:

一、线程初始初始方式

/*多线程初始方式*/ #include <iostream> #include <thread> #include <string> using namespace std; void printALL(int a,int b,int c){ cout<<a<<" "<<b<<" "<<c<<endl; } void add(int a,int b,int& c){ c = a+b; } void printString(const string& info,const string& info2){ cout<<"hello "<<info<<" "<<info2<<endl; } //====================这个线程的初始化函数可以多看看来理解 void testThreadInit(){ int a=3; int b=4; int c=5; thread t([=](){ printALL(a,b,c); }); t.join(); thread t2(printALL,a,b,c); t2.join(); thread t3([=,&c](){ add(a,b,c); }); t3.join(); cout<<"after add: "<<c<<endl; //c是引用,必须使用ref(c) c=0; thread t4(add,a,b,ref(c)); t4.join(); cout<<"after add: "<<c<<endl; string abc("abc"); string def("def"); thread t5([&](){ printString(abc,def); }); t5.join(); //效率比引用低 thread t6(printString,abc,def); t6.join(); //使用cref:常引用 thread t7(printString,cref(abc),cref(def)); t7.join(); } int main(){ testThreadInit(); return 0; }

执行结果:

3 4 5 3 4 5 after add: 7 after add: 7 hello abc def hello abc def hello abc def

二、thread的两种死法

//=====================================三、thread 的两种死法detach和join==================== /* 生成一个线程,需要告诉编译器是否进行管理 1)通过join(),自己管理 2)通过detach(),不管理 参考;https://www.cnblogs.com/douzujun/p/10841797.html //*/ #include <iostream> #include <thread> #include <chrono> using namespace std; class Obj{ public: Obj(){ cout<<"hello\n"; } ~Obj(){ cout<<"world\n"; } }; void joinWorker(){ } void detachWorker(){ Obj obj; this_thread::sleep_for(chrono::seconds(1)); //如果程序执行时间长,则可能不会调用析构函数 } ///**使用detach(),不管理 * detach适合不会出错,生命周期比整个程序短,不想管理的程序 * 缺点: * 如果程序执行时间长,则可能不会调用析构函数*/ int main(){ // Obj obj; thread j(joinWorker); thread w(detachWorker); w.detach(); if(j.joinable()) j.join(); // w.join(); //w线程不能再join() return 0; } /**使用join(),自己进行管理*/ 如果遇到异常,没有调用join,那我们可以自己写一个析构调用join() class ThreadGuard{ public: ThreadGuard(thread& t): m_thread(t){ } ~ThreadGuard(){ if(m_thread.joinable()) m_thread.join(); } private: thread& m_thread; }; int main(){ Obj obj; //方法2:自己写一个析构调用 thread j(joinWorker); ThreadGuard t(j); //方法1: // thread j(joinWorker); // if(j.joinable()) // j.join(); return 0; } /**原始情况*/ int main(){ Obj obj; thread j(joinWorker); return 0; /*运行结果: * hello terminate called without an active exception Process finished with exit code 3 创建了对象之后,没有调用析构函数. 这是因为创建了线程后,没有对线程进行管理,线程不结束,main线程就不能继续,导致一直存在*/ } //=====================================lambda函数乱入一下~~======================= #include <iostream> #include <functional> using namespace std; struct Print{ //结构成员函数 void operator()(int a,int b ,int c) const{ cout<<"print 1:"<<"a "<<a<<" b "<<b<<" c "<<c<<endl; } }; void printInfo(int a,int b,int c){ //单纯函数 cout<<"print 2:"<<"a "<<a<<" b "<<b<<" c "<<c<<endl; } template <typename T1,typename T2,typename T3> void templatePrint(T1 a,T2 b,T3 c){ //模板函数 cout<<"print 3:"<<"a "<<a<<" b "<<b<<" c "<<c<<endl; } struct TemplatePrint{ //模板结构成员函数 template<typename T1,typename T2,typename T3> void operator() (T1 a,T2 b,T3 c)const{ cout<<"print 4:"<<"a "<<a<<" b "<<b<<" c "<<c<<endl; } }; template <typename Func> void printUserFunc(Func func,int a,int b,int c){ func(a,b,c); } int main(){ Print printUserClass; TemplatePrint printUserTempClass; printInfo(1,2,3); templatePrint(11,22,33); printUserClass(111,222,333); printUserTempClass(1111,2222,3333); //1 lambda C++ //方式1 auto local = [](int a,int b,int c){ cout<<"a "<<a<<" b "<<b<<" c "<<c<<endl; }; local(123,123,123); printUserFunc(local,121,212,313); //方式2 //1 lambda C++ //方式3 printUserFunc([](int a,int b,int c){ cout<<"a "<<a<<" b "<<b<<" c "<<c<<endl; },121,212,313); //2 值拷贝 int a=23,b=34,c=45; auto local2 = [a,b,c](){ cout<<"a "<<a<<" b "<<b<<" c "<<c<<endl; }; local2(); //3 传引用 auto local3 = [&](){ // &:外部引用 和 =: 外部拷贝 cout<<"a "<<a<<" b "<<b<<" c "<<c<<endl; }; local3(); return 0; }

三、几种锁的方式

#include <iostream> #include <thread> #include <mutex> #include <string> #include <fstream> using namespace std; std::mutex mu; class LogFile{ mutex _mu; ofstream f; public: LogFile(){ f.open("log.txt"); } ~LogFile(){ f.close(); } void shared_print(string msg,int id){ 2 使用unique_lock defer_lock设置初始化的时候不进行默认的上锁操作 unique_lock<mutex> guard(_mu,defer_lock); //设置初始化时为不上锁的操作 //do something 1 guard.lock(); //do something protected guard.unlock(); //do something 2 guard.lock(); f<<msg<<id<<endl; cout<<msg<<id<<endl; //结束的时候析构guard会临时解锁 1 使用unique_lock提供的lock()unlock()接口,guard声明的时候默认为上锁的状态 unique_lock<mutex> guard(_mu); cout<<"1 do something here..."<<endl; guard.unlock();//临时解锁 cout<<"2 do something here..."<<endl; guard.lock();//继续上锁 f<<msg<<id<<endl; cout<<msg<<id<<endl; //结束时析构guard会临时解锁 guard.unlock();//这句话可要可不要,不写的话析构的时候也会自动执行 0 直接使用guard进行保护所操作 lock_guard<mutex> guard(mu); f<<msg<<id<<endl; } }; void function_1(LogFile& log){ for(int i=0;i>-100;i--){ log.shared_print(string("From t1: "),i); } } int main(){ LogFile log; thread t1(function_1,ref(log)); for(int i=0;i<100;i++){ log.shared_print(string("From main: "),i); } t1.join(); return 0; } void shared_print(string msg,int id){ std::lock_guard<std::mutex> guard(mu); mu.lock();//上锁 cout<<msg<<id<<endl; mu.unlock(); } 普通函数 无参 void function_1() { for(int i=0; i>-100; i--) shared_print(string("From t1:"),i); } int main() { std::thread t1(function_1); for(int i=0; i<100; i++) shared_print(string("From t2:"),i); t1.join(); return 0; } #include <thread> #include <deque> #include <mutex> #include <condition_variable> using namespace std; deque<int> q; mutex mu; condition_variable cond; //条件变量和mutex一起使用的是多线程编程的常用套餐 void function_1(){ int count =10; while(count >0){ unique_lock<mutex> locker(mu); q.push_front(count); locker.unlock(); //生产者已经把数据放进缓冲队列中了,可以唤醒消费者来取数据了 cond.notify_one(); //Notify one waiting thread,if there is one this_thread::sleep_for(chrono::seconds(1)); count--; } } void function_2(){ int data = 0; while(data!=1){ unique_lock<mutex> locker(mu); // 结合condition_variable来控制阻塞和唤醒 while(q.empty()) cond.wait(locker);//unlock mutex and wait to be notified; data = q.back(); q.pop_back(); locker.unlock(); cout<<"t2 got a value from t1: "<<data<<endl; // if(!q.empty()){ // data = q.back(); // q.pop_back(); // locker.unlock(); // cout<<"t2 got a value from t1: "<<data <<endl; // }else{ // locker.unlock(); // //因为t1放入数据的时候睡眠了1秒钟,而取数据这里在这1s内会做很多无用功,所以让它也睡0.5s // this_thread::sleep_for(chrono::milliseconds(500)); // } } } int main(){ thread t1(function_1); thread t2(function_2); t1.join(); t2.join(); return 0; }
最新回复(0)