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 }