C++工程师面试宝典系列之多线程编程
2017-02-12 21:33
337 查看
3.数据竞争与互斥对象
=======================================================================================
4.死锁
(1)首先需要评估程序是否需要2个以上的mutex,如果一个就可以满足要求,则不存在死锁的问题;
(2)避免在使用mutex的同时去调用不熟悉的函数,可能这个函数包含了另外的锁;
(3)如果需要同时使用两个mutex,则可以使用c++标准库提供的lock函数,确保mutex的顺序是相同的;
=======================================================================================
4.Unique Lock 和 Lazy Initialization
=======================================================================================
5.条件变量
=======================================================================================
6.Future , Promise 和 async()
(1)future类是一个可以从未来获取某个变量的类,future的get函数只能被调用一次;
(2)async()不一定会创建子线程,取决于async()的第一个参数;
=======================================================================================
7.使用可调用对象
8.packaged_task
=======================================================================================
9.回顾和时间约束
#include <iostream> #include <thread> #include <string> using namespace std; void function_1() { for (int i = 0; i > -100;i--) cout << "From t1:" <<i<< endl; } //主线程和t1线程竞争来执行cout int main() { thread t1(function_1); for (int i = 0; i < 100; i++) cout << "From main:" << i << endl; t1.join(); return 0; }
#include <iostream> #include <thread> #include <string> #include <mutex> using namespace std; mutex mu; void shared_print(string msg, int id) { mu.lock(); cout << msg << id << endl; //互斥对象,可能会发生异常 mu.unlock(); } void function_1() { for (int i = 0; i > -100;i--) shared_print("From t1:",i); } int main() { thread t1(function_1); for (int i = 0; i < 100; i++) shared_print("From main::", i); t1.join(); return 0; }
#include <iostream> #include <thread> #include <string> #include <mutex> using namespace std; mutex mu; void shared_print(string msg, int id) { lock_guard<mutex> guard(mu); //mu.lock(); cout << msg << id << endl; //互斥对象,可能会发生异常 //mu.unlock(); } void function_1() { for (int i = 0; i > -100;i--) shared_print("From t1:",i); } int main() { thread t1(function_1); for (int i = 0; i < 100; i++) shared_print("From main::", i); t1.join(); return 0; }
#include <iostream> #include <thread> #include <string> #include <mutex> #include <fstream> using namespace std; class LofFile { public: LofFile(){ f.open("log.txt"); } void shared_print(string id, int value) { lock_guard<mutex> locker(m_mutex); f << "From" << id << ":" << value << endl; } //ofstrteam& GetStream(){return f;} /* void processf(void fun(ofstream&)) { fun(f); } */ protected: private: mutex m_mutex; ofstream f; }; void function_1(LofFile& log) { for (int i = 0; i > -100;i--) log.shared_print("From t1:",i); } int main() { LofFile log; thread t1(function_1,ref(log)); for (int i = 0; i < 100; i++) log.shared_print("From main::", i); t1.join(); return 0; }
=======================================================================================
4.死锁
#include <iostream> #include <thread> #include <string> #include <mutex> #include <fstream> using namespace std; class LofFile { mutex m_mutex; ofstream f; //被m_mutex保护的对象 public: LofFile(){ f.open("log.txt"); //构造函数打开log.txt文件 } void shared_print(string id, int value) { lock_guard<mutex> locker(m_mutex); cout<< "From" << id << ":" << value << endl; } }; void function_1(LofFile& log) { for (int i = 0; i > -100;i--) log.shared_print("From t1:",i); } int main() { LofFile log; thread t1(function_1,ref(log)); for (int i = 0; i < 100; i++) log.shared_print("From main::", i); t1.join(); return 0; }
#include <iostream> #include <thread> #include <string> #include <mutex> #include <fstream> using namespace std; class LofFile { mutex m_mutex; mutex m_mutex2; ofstream f; //被m_mutex保护的对象 public: LofFile(){ f.open("log.txt"); //构造函数打开log.txt文件 } void shared_print(string id, int value) { lock_guard<mutex> locker(m_mutex); lock_guard<mutex> locker2(m_mutex2); cout<< "From" << id << ":" << value << endl; } void shared_print2(string id, int value) { lock_guard<mutex> locker2(m_mutex2); lock_guard<mutex> locker(m_mutex); cout << "From" << id << ":" << value << endl; } }; void function_1(LofFile& log) { for (int i = 0; i > -100;i--) log.shared_print("From t1:",i); } int main() { LofFile log; thread t1(function_1,ref(log)); for (int i = 0; i < 100; i++) log.shared_print2("From main::", i); t1.join(); return 0; }
void shared_print(string id, int value) { lock_guard<mutex> locker(m_mutex); lock_guard<mutex> locker2(m_mutex2); cout<< "From" << id << ":" << value << endl; } void shared_print2(string id, int value) { lock_guard<mutex> locker2(m_mutex); lock_guard<mutex> locker(m_mutex2); cout << "From" << id << ":" << value << endl; }
#include <iostream> #include <thread> #include <string> #include <mutex> #include <fstream> using namespace std; class LofFile { mutex m_mutex; mutex m_mutex2; ofstream f; //被m_mutex保护的对象 public: LofFile(){ f.open("log.txt"); //构造函数打开log.txt文件 } void shared_print(string id, int value) { lock(m_mutex, m_mutex2); lock_guard<mutex> locker(m_mutex,adopt_lock); lock_guard<mutex> locker2(m_mutex2,adopt_lock); cout<< "From" << id << ":" << value << endl; } void shared_print2(string id, int value) { lock(m_mutex, m_mutex2); lock_guard<mutex> ce5d locker2(m_mutex2,adopt_lock); lock_guard<mutex> locker(m_mutex,adopt_lock); cout << "From" << id << ":" << value << endl; } }; void function_1(LofFile& log) { for (int i = 0; i > -100;i--) log.shared_print("From t1:",i); } int main() { LofFile log; thread t1(function_1,ref(log)); for (int i = 0; i < 100; i++) log.shared_print2("From main::", i); t1.join(); return 0; }避免死锁的总结:
(1)首先需要评估程序是否需要2个以上的mutex,如果一个就可以满足要求,则不存在死锁的问题;
(2)避免在使用mutex的同时去调用不熟悉的函数,可能这个函数包含了另外的锁;
(3)如果需要同时使用两个mutex,则可以使用c++标准库提供的lock函数,确保mutex的顺序是相同的;
=======================================================================================
4.Unique Lock 和 Lazy Initialization
#include <iostream> #include <thread> #include <string> #include <mutex> #include <fstream> using namespace std; class LofFile { mutex m_mutex; ofstream f; //被m_mutex保护的对象 public: LofFile(){ f.open("log.txt"); //构造函数打开log.txt文件 } void shared_print(string id, int value) { //lock_guard<mutex> locker(m_mutex); unique_lock<mutex> locker(m_mutex,defer_lock); //... locker.lock(); f<< "From" << id << ":" << value << endl; locker.unlock(); //... locker.lock(); unique_lock<mutex> locker2 = move(locker); } }; void function_1(LofFile& log) { for (int i = 0; i > -100;i--) log.shared_print(string("From t1:"),i); } int main() { LofFile log; thread t1(function_1,ref(log)); for (int i = 0; i < 100; i++) log.shared_print("From main::", i); t1.join(); return 0; }
#include <iostream> #include <thread> #include <string> #include <mutex> #include <fstream> using namespace std; class LofFile { mutex m_mutex; //mutex m_mutex_open; once_flag m_flag; ofstream f; //被m_mutex保护的对象 public: LofFile(){ //f.open("log.txt"); //构造函数打开log.txt文件 } void shared_print(string id, int value) { /*{ unique_lock<mutex> locker(m_mutex_open, defer_lock); if (!f.is_open()) { f.open("log.txt"); } }*/ call_once(m_flag, [&](){f.open("log.txt"); }); unique_lock<mutex> locker(m_mutex,defer_lock); f<< "From" << id << ":" << value << endl; } }; void function_1(LofFile& log) { for (int i = 0; i > -100;i--) log.shared_print(string("From t1:"),i); } int main() { LofFile log; thread t1(function_1,ref(log)); for (int i = 0; i < 100; i++) log.shared_print("From main::", i); t1.join(); return 0; }
=======================================================================================
5.条件变量
#include <iostream> #include <thread> #include <string> #include <mutex> #include <fstream> #include <deque> #include <functional> #include <condition_variable> using namespace std; deque<int> q; //声明一个全局变量,类型是一个整型的队列 mutex mu; //声明一个互斥对象mu condition_variable cond; //条件变量 void function_1() { int count = 10; while (count = 10){ unique_lock<mutex> locker(mu); q.push_front(count); //每一次循环都会将一个数字push到队列q中 locker.unlock(); //cond.notify_one();//会激活整个条件的线程 cond.notify_all();//线程1传入数据后通知线程2运行 this_thread::sleep_for(chrono::seconds(1));//线程sleep一秒钟 count--; } } void function_2(){ int data = 0; while (data != 1){ unique_lock<mutex> locker(mu); cond.wait(locker, [](){return !q.empty(); });//重复的加解锁,只能使用unique_lock,不能使用lock_guard //if (!q.empty()){ //如果队列不空,队列会pop出一个数 data = q.back(); q.pop_back(); locker.unlock(); cout << "t2 get a value from t1:" << data << endl; } /* else{ locker.unlock(); //如果队列为空,则解锁,进入下一个循环 //this_thread::sleep_for(chrono::milliseconds(10)); //如果队列为空,等待10秒后进入下一个循环 } */ } //function_1是数据的生成者,function_2是数据的消费者 int main(){ thread t1(function_1); thread t2(function_2); t1.join(); t2.join(); return 0; }
=======================================================================================
6.Future , Promise 和 async()
(1)future类是一个可以从未来获取某个变量的类,future的get函数只能被调用一次;
(2)async()不一定会创建子线程,取决于async()的第一个参数;
async(lauch::deferred,factorial.4);//延迟启动
async(launch::async,factorial,4);//创建另一个子线程来启动factorial
#include <iostream> #include <thread> #include <string> #include <mutex> #include <fstream> #include <future> using namespace std; /* //全局变量 mutex mu;//需要lock和unlock函数 condition_variable cond;//需要notify和wait函数 */ //int factorial(int N,int & x ){//添加一个参数,创建引用x int factorial(int N){ int res = 1; for (int i = N; i > 1; i--) res *= i; cout << "result is :" <<res<< endl; return res; } int main(){ int x; //thread t1(factorial,4,ref(x));//创建一个变量x,传递给线程1 future<int> fu = async(factorial,4); x = fu.get(); //t1.join(); return 0; }
#include <iostream> #include <thread> #include <string> #include <mutex> #include <fstream> #include <future> using namespace std; int factorial(future<int>& f){ int res = 1; int N = f.get(); for (int i = N; i > 1; i--) res *= i; cout << "result is :" <<res<< endl; return res; } int main(){ int x; promise<int> p; future<int> f = p.get_future(); p.get_future(); //thread t1(factorial,4,ref(x));//创建一个变量x,传递给线程1 future<int> fu = async(launch::async,factorial,ref(f)); p.set_value(4); x = fu.get(); cout << "Get form child" << x << endl; //t1.join(); return 0; }
#include <iostream> #include <thread> #include <string> #include <mutex> #include <fstream> #include <future> using namespace std; int factorial(shared_future<int> f){ int res = 1; int N = f.get();//抛出异常 std::future_errc::broken_promise for (int i = N; i > 1; i--) res *= i; cout << "result is :" <<res<< endl; return res; } int main(){ int x; promise<int> p; //promise<int> p2 = move(p); future<int> f = p.get_future(); //p.get_future(); //thread t1(factorial,4,ref(x));//创建一个变量x,传递给线程1 shared_future<int> sf = f.share(); future<int> fu = async(launch::async,factorial,sf); future<int> fu2 = async(launch::async, factorial, sf); future<int> fu3 = async(launch::async, factorial, sf); future<int> fu4 = async(launch::async, factorial, sf); //...10线程 p.set_value(4); //x = fu.get(); //cout << "Get form child" << x << endl; //t1.join(); return 0; }
=======================================================================================
7.使用可调用对象
#include <iostream> #include <thread> #include <string> #include <mutex> #include <fstream> #include <future> using namespace std; class A { public: void f(int x, char c){} int operator()(int N){ return 0; } //函数重载了 }; void foo(int x){} int main(){ A a; //两种方法创建子线程,使用thread或者async函数 thread t1(a,6);//传递a的拷贝给子线程 thread t2(ref(a), 6);//传递a的引用给子线程 thread t3(move(a), 6);//将a从主线程移动到子线程中,a在主线程中不再有效 thread t4(A(),6);//传递临时创建的a对象给子线程 thread t5(foo, 6);//全局函数来创建子线程 thread t6([](int x){return x*x; },6); thread t7(&A::f,a,8,'w');//传递a的拷贝的成员函数给子线程 thread t8(&A::f, &a, 8, 'w');//传递a的地址的成员函数给子线程 async(launch::async,a,6); return 0; }=======================================================================================
8.packaged_task
#include <iostream> #include <thread> #include <string> #include <mutex> #include <fstream> #include <future> #include <deque> using namespace std; int factorial(int N){ int res = 1; for (int i = N; i > 1; i--) res *= 1; cout << "Result is:" << res << endl; return res; } std::deque<packaged_task<int()>> task_q; std::mutex mu; std::condition_variable cond; void thread_1() { packaged_task<int()> t; { std::unique_lock<mutex> locker(mu); cond.wait(locker, []{return !task_q.empty();}); t = std::move(task_q.front()); } t(); } int main(){ std::thread t1(thread_1); std::packaged_task<int()> t(bind(factorial, 6)); std::future<int> ret = t.get_future();//获得与packaged_task共享状态相关联的future对象。 { std::lock_guard<std::mutex> locker(mu); task_q.push_back(std::move(t)); } cond.notify_one(); int value = ret.get();//等待任务完成并获取结果。 t1.join(); /* thread t1(factorial,6); packaged_task<int()> t(bind(factorial,6)); future<int> ret = t.get_future();//获得与packaged_task共享状态相关联的future对象。 int value = ret.get();//等待任务完成并获取结果。 */ /* auto t = bind(factorial, 6); t(); */ return 0; }
=======================================================================================
9.回顾和时间约束
#include <mutex> #include <fstream> #include <future> #include <deque> using namespace std; int factorial(int N){ int res = 1; for (int i = N; i > 1; i--) res *= 1; cout << "Result is:" << res << endl; return res; } std::deque<packaged_task<int()>> task_q; std::mutex mu; std::condition_variable cond; int main(){ std::thread t1(factorial,6); std::this_thread::sleep_for(chrono::milliseconds(3)); chrono::steady_clock::time_point tp = chrono::steady_clock::now() + chrono::milliseconds(4); std::this_thread::sleep_until(tp); std::mutex mu; std::unique_lock<std::mutex> locker(mu); locker.try_lock_for(chrono::milliseconds(3)); locker.try_lock_until(tp); std::condition_variable cond; cond.wait_for(locker, chrono::milliseconds(3)); cond.wait_until(locker,tp); std::promise<int> p; std::future<int> f = p.get_future(); f.wait_for(chrono::milliseconds(3)); f.wait_until(tp); return 0; }=======================================================================================
相关文章推荐
- C++工程师面试宝典系列之多线程编程
- C++工程师面试宝典系列之多线程编程
- C++工程师面试宝典系列之MFC开发
- C++工程师面试宝典系列之Linux编程之GCC编译工具实践
- C++工程师面试宝典系列之C/C++经典面试题
- C++工程师面试宝典系列之Linux编程之GCC编译工具实践
- C++工程师面试宝典系列之C/C++经典面试题
- 数据科学工程师面试宝典系列之一--Python爬虫实战
- 数据科学工程师面试宝典系列之二---Python机器学习kaggle案例:泰坦尼克号船员获救预测
- 数据科学工程师面试宝典系列---数据挖掘算法原理
- 数据科学工程师面试宝典系列---R语言入门
- 数据科学工程师面试宝典系列---旅游评论数据中的自然语言处理
- C++程序设计实践学材系列(15)——1.3.1 帮电气工程师计算电阻值
- Qt C++ 并发,并行,多线程编程系列1 什么是并发
- 数据科学工程师面试宝典系列之一----Python爬虫
- 数据科学工程师面试宝典系列之四---MySQL基础
- 数据科学工程师面试宝典系列之二---Python机器学习kaggle案例:泰坦尼克号船员获救预测
- 数据科学工程师面试宝典系列之一--Python爬虫实战
- C++ GUI Programming with Qt3(系列三 试翻)
- 微软软件实现技术授课系列内容之三:Project in C++ Coding Practice