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 }


浙公网安备 33010602011771号