C++多线程-chap2多线程通信和同步1
这里,只是记录自己的学习笔记。
顺便和大家分享多线程的基础知识。然后从入门到实战。有代码。
知识点来源:
https://edu.51cto.com/course/26869.html
1.多线程同步通信
1.1多线程状态
1.1.1线程状态说明:
- 初始化 ( Init ) :该线程正在创建。
- 就绪 ( Ready ):该线程在继续列表中,等待CPU调度。
- 运行 (Running):该线程正在运行。
- 阻塞 ( Blocked ):该线程被阻塞挂起。Blocked状态包括:pend(锁、事件、信号量等阻塞)、suspend(主动pend)、delay(延时阻塞)、pendtime(因为锁、事件、信号量时间等 超时等待)。
- 退出 ( Exit ) :该线程运行结束,等待父线程回收其控制块资源。
1.1.2 竞争状态(Race Condition)和临界区(Critical Section)
竞争状态(Race Condition)
- 多线程同时读写共享数据。
临界区(Critical Section)
- 读写共享数据的代码片段
避免竞争状态策略,对临界区进行保护,同时只能有一个线程进入临界区。
mutex 的 lock() 和 try_lock() 方法的使用。
1 #include2 #include 3 #include <string> 4 #include 5 using namespace std; 6 static mutex mux; 7 8 void TestThread() { 9 10 //对于锁,尽可能晚的申请;尽可能早的释放。。。 11 12 //获取锁资源,如果没有则阻塞等待 13 mux.lock();//处于阻塞状态,cpu资源是释放的。。。 14 cout << "========================================" << endl; 15 cout << "test 001" << endl; 16 cout << "test 002" << endl; 17 cout << "test 003" << endl; 18 cout << "========================================" << endl; 19 mux.unlock(); 20 } 21 22 23 void TestThread2() { 24 25 for (;;) { 26 //注意,调用 try_lock 是有开销的,在try_lock之后,必须跟一个sleep_for等待若干时间(释放cpu资源),否则一直try_lock会把cpu资源耗尽。 27 if (!mux.try_lock()) { 28 cout << "....." < endl; 29 this_thread::sleep_for(3000ms); 30 continue; 31 } 32 cout << "========================================" << endl; 33 cout << "test 001" << endl; 34 cout << "test 002" << endl; 35 cout << "test 003" << endl; 36 cout << "========================================" << endl; 37 mux.unlock(); 38 this_thread::sleep_for(1000ms); 39 } 40 } 41 42 43 44 int main() 45 { 46 //for (int i = 0; i < 10; i++) { 47 // thread th(TestThread); 48 // th.detach(); 49 //} 50 51 for (int i = 0; i < 10; i++) { 52 thread th(TestThread2); 53 th.detach(); 54 } 55 56 getchar(); 57 return 0; 58 }
互斥锁等待坑,线程抢占不到资源.
特别注意,unlock之后,不要再立即进入lock。预留一点时间出来。
1 #include2 #include 3 #include <string> 4 #include 5 using namespace std; 6 7 //互斥锁等待坑,线程抢占不到资源 8 static mutex mux; 9 10 void ThreradMainMux(int i) { 11 // 12 for (;;) { 13 14 mux.lock(); 15 cout << i << "[in]" << endl; 16 this_thread::sleep_for(1000ms); 17 mux.unlock(); 18 19 //特别注意,unlock之后,不要再立即进入lock。预留一点时间出来。 20 this_thread::sleep_for(1ms); 21 } 22 } 23 24 int main() { 25 for (int i = 0; i < 3; i++) 26 { 27 thread th(ThreradMainMux,i); 28 th.detach(); 29 } 30 31 getchar(); 32 return 0; 33 }
超时锁的应用 timed_mutex(避免长时间死锁)
1 #include2 #include <string> 3 #include 4 #include 5 using namespace std; 6 7 8 9 //超时锁的应用 timed_mutex(避免长时间死锁) 10 11 timed_mutex tmux; 12 13 void ThreadMainTime(int i) { 14 for (;;) { 15 if (!tmux.try_lock_for(std::chrono::milliseconds(1000))) { 16 cout << i << "[try_lock_for] timeout" << endl; 17 continue; 18 } 19 cout << i << "[in]" << endl; 20 21 this_thread::sleep_for(2000ms); 22 tmux.unlock(); 23 this_thread::sleep_for(1ms); 24 } 25 } 26 27 28 int main() { 29 30 for (int i = 0; i < 3; i++) { 31 thread th(ThreadMainTime, i); 32 33 th.detach(); 34 } 35 36 getchar(); 37 return 0; 38 }
//递归锁(可重入) recursive mutex 和 recursive_timed_mutex 用于业务组合
// 同一个线程中的同一把锁可以锁多次,避免了一些不必要的死锁
//组合业务,用到同一把锁
1 #include2 #include <string> 3 #include 4 #include 5 using namespace std; 6 //递归锁(可重入) recursive mutex 和 recursive_timed_mutex 用于业务组合 7 8 9 // 同一个线程中的同一把锁可以锁多次,避免了一些不必要的死锁 10 //组合业务,用到同意把锁 11 recursive_mutex rmux; 12 13 14 void Task1() { 15 rmux.lock(); 16 cout << "task1 [in]" << endl; 17 rmux.unlock(); 18 } 19 20 21 void Task2() { 22 rmux.lock(); 23 cout << "task2 [in]" << endl; 24 rmux.unlock(); 25 } 26 27 28 void ThreadMainRec(int i) { 29 for (;;) { 30 rmux.lock(); 31 Task1(); 32 cout << i << "[in]" << endl; 33 this_thread::sleep_for(2000ms); 34 Task2(); 35 rmux.unlock(); 36 this_thread::sleep_for(1ms); 37 } 38 } 39 40 41 int main() { 42 for (int i = 0; i < 3; i++) { 43 thread th(ThreadMainRec, i); 44 th.detach(); 45 } 46 47 48 getchar(); 49 return 0; 50 }