线程管理
多线程的执行函数尽量用传引用,以减少不必要资源开销;根据hardware_concurrency得到核心数来决定开多线程的数量;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <iostream> #include <thread> #include <unistd.h> using namespace std;
class Fctor{ public: void operator()(string& msg) { cout <<"from f1:" << msg<<endl; msg = "changed"; } };
int main() { string s = "not changed"; cout << this_thread::get_id()<<endl; thread t1((Fctor()), ref(s)); t1.join();
cout << s << endl; cout << thread::hardware_concurrency() << endl;
return 0; }
|
数据竞争及互斥对象
避免数据竞争,用lock_guard解决抛出异常的问题;lock_guard保证线程独占资源而安全
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include <iostream> #include <string> #include <thread> #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; }
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; }
|
死锁
避免死锁:
- 评估线程是否需要两个或以上的互斥对象
- 避免在锁住资源的同时去调用一些不熟悉的函数
- 使用lock函数帮助mutex顺序一致
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #include <iostream> #include <string> #include <thread> #include <mutex> #include <fstream> using namespace std;
class LofFile { public: LofFile() {}
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> locker2(m_mutex2, adopt_lock); lock_guard<mutex> locker(m_mutex, adopt_lock); cout << "From" << id << ": " << value << endl; }
private: mutex m_mutex; mutex m_mutex2; 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_print2("from main: ", i);
t1.join(); return 0; }
|
Unique Lock和lazy Initialization
加锁的方式:
- lock_guard
- mutex.lock
- unique_lock(推荐,但占用更多系统资源)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| #include <iostream> #include <string> #include <thread> #include <mutex> #include <fstream> using namespace std;
class LofFile { public: LofFile(){ f.open("log.txt"); } void shared_print(string id, int value) { unique_lock<mutex> locker(m_mutex, defer_lock);
locker.lock(); f << id <<": " << value << endl; locker.unlock();
locker.lock();
unique_lock<mutex> locker2 = move(locker); }
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; }
|
生产者和消费者问题
结合unique_lock和lambda,让线程之间高效相互响应执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| #include <functional> #include <iostream> #include <fstream> #include <string> #include <mutex> #include <thread> #include <deque> #include <condition_variable>
using namespace std;
deque<int> q; mutex mu; condition_variable cond;
void function_1() { int count = 10; while(count > 0) { unique_lock<mutex> locker(mu); q.push_front(count); locker.unlock(); cond.notify_one(); this_thread::sleep_for(chrono::seconds(1)); count--; } }
void function_2() { int data = 0; while(data!=1) { unique_lock<mutex> locker(mu); cond.wait(locker, [](){ return !q.empty(); }); data = q.back(); q.pop_back(); locker.unlock(); cout <<"t2 got a value from t1: " << data<<endl; } }
int main() { thread t1(function_1); thread t2(function_2); t1.join(); t2.join(); return 0;
}
|