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 #include 
 2 #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 #include 
 2 #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 #include 
 2 #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 #include 
 2 #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 }