C++多线程练习

题目1:子线程循环 10 次,接着主线程循环 100 次,接着又回到子线程循环 10 次,接着再回到主线程又循环 100 次,如此循环50次,试写出代码

代码1:

复制代码
 1 #include <iostream>
 2 #include <thread>
 3 #include <mutex>
 4 using namespace std;
 5 
 6 const int count = 50;
 7 int flag = 10;
 8 std::mutex mtex;
 9 
10 void fun(const int num, const string &str) {
11     for(int i = 0; i < count; ++i) {
12         while(num != flag) std::this_thread::yield();
13         mtex.lock();
14         for(int j = 0; j < num; ++j) {
15             cout << str << endl;
16         }
17         std::this_thread::sleep_for(std::chrono::seconds(1));
18         flag = (flag == 10 ? 100 : 10);
19         mtex.unlock(); 
20     }
21 }
22 
23 int main(void) {
24     auto start = std::chrono::high_resolution_clock::now();
25     thread child(fun, 10, "child");
26     fun(100, "father");
27     child.join();
28     auto end = std::chrono::high_resolution_clock::now();
29     std::chrono::duration<double, std::milli> elapsed = end - start;
30     cout << elapsed.count() << endl;
31 
32     return 0;
33 }
复制代码

代码2:

复制代码
 1 #include <iostream>
 2 #include <thread>
 3 #include <mutex>
 4 #include <condition_variable>
 5 using namespace std;
 6 
 7 const int count = 50;
 8 int flag = 10;
 9 condition_variable cv;
10 std::mutex mtex;
11 
12 void fun(const int num, const string &str) {
13     for(int i = 0; i < count; ++i) {
14         unique_lock<std::mutex> lk(mtex);
15         cv.wait(lk, [&]{
16             return num == flag;
17         });
18         for(int j = 0; j < num; ++j) {
19             cout << str << endl;
20         }
21         std::this_thread::sleep_for(std::chrono::seconds(1));
22         flag = (flag == 10 ? 100 : 10);
23         mtex.unlock();
24         cv.notify_one();
25     }
26 }
27 
28 int main(void) {
29     auto start = std::chrono::high_resolution_clock::now();
30     thread child(fun, 10, "child");
31     fun(100, "father");
32     child.join();
33     auto end = std::chrono::high_resolution_clock::now();
34     std::chrono::duration<double, std::milli> elapsed = end - start;
35     cout << elapsed.count() << endl;
36 
37     return 0;
38 }
复制代码

 

题目2:编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推

代码1:

复制代码
 1 #include <iostream>
 2 #include <thread>
 3 #include <mutex>
 4 using namespace std;
 5 
 6 int main(void) {
 7     std::mutex mtex;
 8     int cnt = 0;
 9     auto work = [&](char ch, int num) {
10         while(num--) {
11             while(ch != cnt + 'A') std::this_thread::yield();
12             std::unique_lock<std::mutex> lk(mtex);
13             cout << ch;
14             cnt = (cnt + 1) % 3;
15             lk.unlock();
16         }
17     };
18     thread t1(work, 'A', 10);
19     thread t2(work, 'B', 10);
20     work('C', 10);
21 
22     t1.join();
23     t2.join();
24 
25     return 0;
26 }
复制代码

代码2:

复制代码
 1 #include <iostream>
 2 #include <thread>
 3 #include <mutex>
 4 #include <chrono>
 5 #include <condition_variable>
 6 using namespace std;
 7 
 8 condition_variable cv;
 9 std::mutex mtex;
10 int cnt = 0;
11 
12 void work(char ch, int num) {
13     while(num--) {
14         std::this_thread::sleep_for(std::chrono::seconds(1));
15         unique_lock<std::mutex> lk(mtex);
16         cv.wait(lk, [&]{
17             return 'A' + cnt == ch;
18         });
19         cout << ch;
20         cnt = (cnt + 1) % 3;
21         lk.unlock();
22         cv.notify_one();
23     }
24 }
25 
26 int main(void) {
27     thread t1(work, 'A', 10);
28     thread t2(work, 'B', 10);
29     work('C', 10);
30 
31     t1.join();
32     t2.join();
33 
34     return 0;
35 }
复制代码

 

题目3:(google笔试题):有四个线程1、2、3、4。线程 1 的功能就是输出1,线程2的功能就是输出2,以此类推.........现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式:

A:1 2 3 4 1 2....

B:2 3 4 1 2 3....

C:3 4 1 2 3 4....

D:4 1 2 3 4 1....

代码:

复制代码
 1 #include <iostream>
 2 #include <thread>
 3 #include <mutex>
 4 #include <fstream>
 5 #include <condition_variable>
 6 using namespace std;
 7 
 8 const string filename = "D://code//c++//ac36";
 9 condition_variable cv;
10 std::mutex mtex;
11 
12 int vis[] = {4, 1, 2, 3};//四个文件上一次分别写入的值
13 
14 ofstream f1(filename + "_A.txt");
15 ofstream f2(filename + "_B.txt");
16 ofstream f3(filename + "_C.txt");
17 ofstream f4(filename + "_D.txt");
18 
19 ofstream *file[4];
20     
21 void solve(const int x, int gg) {
22     while(gg--){
23         for(int i = 0; i < 4; ++i) {
24 
25             std::unique_lock<std::mutex> lk(mtex);
26 
27             if(x == 1) {
28                 cv.wait(lk, [&]{
29                     return vis[i] == 4;
30                 });
31                 (*file[i]) << 1;
32                 vis[i] = 1;
33                 lk.unlock();
34                 cv.notify_all();
35             }else if(x == 2) {
36                 cv.wait(lk, [&]{
37                     return vis[i] == 1;
38                 });
39                 (*file[i]) << 2;
40                 vis[i] = 2;
41                 lk.unlock();
42                 cv.notify_all();
43             }else if(x == 3) {
44                 cv.wait(lk, [&]{
45                     return vis[i] == 2;
46                 });
47                 (*file[i]) << 3; 
48                 vis[i] = 3;
49                 lk.unlock();
50                 cv.notify_all();
51             }else {
52                 cv.wait(lk, [&]{
53                     return vis[i] == 3;
54                 });
55                 (*file[i]) << 4;
56                 vis[i] = 4;
57                 lk.unlock();
58                 cv.notify_all();
59             }
60         }
61     }
62 }
63 
64 int main(void) {
65     file[0] = &f1;
66     file[1] = &f2;
67     file[2] = &f3;
68     file[3] = &f4;
69 
70     thread t1(solve, 1, 10);
71     thread t2(solve, 2, 10);
72     thread t3(solve, 3, 10);
73     solve(4, 10);
74 
75     t1.join();
76     t2.join();
77     t3.join();
78 
79     for(int i = 0; i < 4; ++i) {
80         file[i]->close();
81     }
82     return 0;
83 }
复制代码

 

题目4:有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者读时写者也不能写

代码:

复制代码
 1 #include <iostream>
 2 #include <thread>
 3 #include <mutex>
 4 #include <fstream>
 5 #include <stdio.h>
 6 #include <condition_variable>
 7 using namespace std;
 8 
 9 const string filename = "D://code//c++//ac36.txt";
10 std::condition_variable cv;
11 std::mutex mtx;
12 int cnt = 0;
13 
14 ifstream in(filename);
15 ofstream out(filename, ios::app);
16 
17 void write() {
18     char ch;
19     while(true) {
20         std::unique_lock<std::mutex> lk(mtx);
21         ch = getchar();
22         out << ch;
23         ++cnt;
24         lk.unlock();
25         cv.notify_all();
26     }
27 }
28 
29 void read() {
30     char ch;
31     while(true) {
32         std::unique_lock<std::mutex> lk(mtx);
33         cv.wait(lk, [&]{
34             return cnt > 0;
35         });
36         in >> ch;
37         cout << "cout: " << ch << endl;
38         --cnt;
39     }
40 }
41 
42 int main(void) {
43     cnt = in.tellg();
44 
45     std::thread tw(write);
46     std::thread tr1(read);
47     std::thread tr2(read);
48     std::thread tr3(read);
49 
50     tw.join();
51     tr1.join();
52     tr2.join();
53     tr3.join();
54 
55     in.close();
56     out.close();
57 
58     return 0;
59 }
复制代码

 

题目5:

线程安全的 queue

STL 中的 queue 是非线程安全的,一个组合操作:front();  pop() 先读取队首元素然后删除队首元素,若是有多个线程执行这个组合操作的话,可能会发生执行序列交替执行,导致一些意想不到的行为。因此需要重新设计线程安全的 queue 的接口

代码:

复制代码
 1 #include <iostream>
 2 #include <thread>
 3 #include <mutex>
 4 #include <queue>
 5 #include <chrono>
 6 #include <condition_variable>
 7 using namespace std;
 8 
 9 template <typename T>
10 class thread_safe_queue{
11 private:
12     std::condition_variable cv;
13     std::queue<T> que;
14     std::mutex mtx;
15 
16 public:
17     thread_safe_queue() = default;
18     thread_safe_queue(const std::queue<T> q) : que(q) {}
19     thread_safe_queue(const thread_safe_queue &tsf) {
20         std::unique_lock<std::mutex> lk(mtx);
21         que = tsf.que;
22     }
23     ~thread_safe_queue() = default;
24 
25     void push(const T &value) {
26         std::unique_lock<std::mutex> lk(mtx);
27         que.push(value);
28         lk.unlock();
29         cv.notify_all();
30     }
31 
32     T pop(void) {
33         std::unique_lock<std::mutex> lk(mtx);
34         cv.wait(lk, [&]{
35             return bool(!que.empty());
36         });
37         T value = que.front();
38         que.pop();
39         return value;
40     }
41 
42     bool empty(void) {
43         std::unique_lock<std::mutex> lk(mtx);
44         return que.empty();
45     }
46 };
47 
48 thread_safe_queue<int> q;
49 std::mutex mtx;
50 
51 int main(void) {
52 
53     auto push_value = [&]{
54         for(int i = 0; i < 100; ++i) {
55             q.push(i);
56             std::this_thread::sleep_for(std::chrono::seconds(1));
57         }
58     };
59 
60     auto pop_value = [&]{
61         while(1) {
62             while(!q.empty()) {
63                 std::unique_lock<std::mutex> lk(mtx);
64                 cout << q.pop() << '\n';
65             }
66         }
67     };
68 
69     thread push_thread1(push_value);
70     thread pop_thread1(pop_value);
71     thread pop_thread2(pop_value);
72     thread pop_thread3(pop_value);
73 
74     push_thread1.join();
75     pop_thread1.join();
76     pop_thread2.join();
77     pop_thread3.join();
78 
79     return 0;
80 }
复制代码

 

题目6:编写程序完成如下功能:

1)有一int型全局变量g_Flag初始值为0

2) 在主线称中起动线程1,打印“this is thread1”,并将g_Flag设置为1

3) 在主线称中启动线程2,打印“this is thread2”,并将g_Flag设置为2

4) 线程序1需要在线程2退出后才能退出

5) 主线程在检测到g_Flag从1变为2,或者从2变为1的时候退出

代码1:

复制代码
 1 #include <iostream>
 2 #include <thread>
 3 #include <mutex>
 4 #include <condition_variable>
 5 using namespace std;
 6 
 7 std::condition_variable cv;
 8 std::mutex metx;
 9 int g_Flag = 0;
10 int cnt = 0;
11 bool flag = false;
12 
13 int main(void) {
14     thread t1([&]{
15         std::unique_lock<std::mutex> lk(metx);
16         cout << "this is thread1\n";
17         g_Flag = 1;
18         ++cnt;
19         cv.wait(lk, [&]{{
20             return flag;
21         }});
22         cout << "thread1 exit\n";
23     });
24 
25     thread t2([&]{
26         std::unique_lock<std::mutex> lk(metx);
27         cout << "this is thread2\n";
28         g_Flag = 2;
29         cnt++;
30         flag = true;
31         cv.notify_all();
32         cout << "thread2 exit\n";
33     });
34 
35     t1.detach();//分离线程
36     t2.detach();
37 
38     std::unique_lock<std::mutex> lc(metx);
39     cv.wait(lc, [&]{
40         return cnt >= 2;
41     });
42     cout << "main thread exit\n";
43 
44     return 0;
45 }
复制代码

代码2:

复制代码
 1 #include <iostream>
 2 #include <thread>
 3 #include <mutex>
 4 #include <atomic>
 5 #include <future>
 6 using namespace std;
 7 
 8 atomic<int> g_Flag(0), cnt(0);
 9 
10 void thread1(std::future<int> fu) {
11     cout << "this is thread1\n";
12     g_Flag = 1;
13     ++cnt;
14     fu.get();//线程1阻塞至线程2设置共享状态, get等待异步操作结束并返回结果
15     cout << "thread1 exit\n";
16 }
17 
18 void thread2(std::promise<int> pro) {
19     cout << "this is thread2\n";
20     g_Flag = 2;
21     ++cnt;
22     cout << "thread2 exit\n";
23     pro.set_value(1);//设置共享值
24 }
25 
26 int main(void) {
27     std::promise<int> prom;//创建一个promise对象
28     std::future<int> fu = prom.get_future();//获得promise内部的future,fut将和prom共享prom中的共享状态
29 
30     std::thread t1(thread1, std::move(fu));//通过fut在线程1中得到线程2的状态
31     std::thread t2(thread2, std::move(prom));//通过prom设置线程2中的共享状态
32 
33     t1.detach();
34     t2.detach();
35 
36     while(cnt < 2);
37     cout << "main thread exit\n";
38 
39     return 0;
40 }
复制代码

 

posted @ 2019-07-11 10:25  unique_ptr  阅读(523)  评论(0编辑  收藏  举报