C++ 多线程题目练习总结

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

解答1:

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;

const int count = 50;
int flag = 10;
std::mutex mtex;

void fun(const int num, const string &str) {
  for (int i = 0; i < count; ++i) {
    while (num != flag)
      std::this_thread::yield();
    mtex.lock();
    for (int j = 0; j < num; ++j) {
      cout << str << endl;
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));
    flag = (flag == 10 ? 100 : 10);
    mtex.unlock();
  }
}

int main(void) {
  auto start = std::chrono::high_resolution_clock::now();
  thread child(fun, 10, "child");
  fun(100, "father");
  child.join();
  auto end = std::chrono::high_resolution_clock::now();
  std::chrono::duration<double, std::milli> elapsed = end - start;
  cout << elapsed.count() << endl;

  return 0;
}

解答2

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

#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;

const int count = 50;
int flag = 10;
condition_variable cv;
std::mutex mtex;

void fun(const int num, const string &str) {
  for (int i = 0; i < count; ++i) {
    unique_lock<std::mutex> lk(mtex);
    cv.wait(lk, [&] { return num == flag; });
    for (int j = 0; j < num; ++j) {
      cout << str << endl;
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));
    flag = (flag == 10 ? 100 : 10);
    mtex.unlock();
    cv.notify_one();
  }
}

int main(void) {
  auto start = std::chrono::high_resolution_clock::now();
  thread child(fun, 10, "child");
  fun(100, "father");
  child.join();
  auto end = std::chrono::high_resolution_clock::now();
  std::chrono::duration<double, std::milli> elapsed = end - start;
  cout << elapsed.count() << endl;

  return 0;
}

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

写法1

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;

int main(void) {
    std::mutex mtex;
    int cnt = 0;
    auto work = [&](char ch, int num) {
        while(num--) {
            while(ch != cnt + 'A') std::this_thread::yield();
            std::unique_lock<std::mutex> lk(mtex);
            cout << ch;
            cnt = (cnt + 1) % 3;
            lk.unlock();
        }
    };
    thread t1(work, 'A', 10);
    thread t2(work, 'B', 10);
    work('C', 10);

    t1.join();
    t2.join();

    return 0;
}

写法2

 #include <iostream>
 #include <thread>
 #include <mutex>
 #include <chrono>
 #include <condition_variable>
 using namespace std;
 
 condition_variable cv;
 std::mutex mtex;
 int cnt = 0;
 
 void work(char ch, int num) {
     while(num--) {
         std::this_thread::sleep_for(std::chrono::seconds(1));
         unique_lock<std::mutex> lk(mtex);
         cv.wait(lk, [&]{
             return 'A' + cnt == ch;
         });
         cout << ch;
         cnt = (cnt + 1) % 3;
         lk.unlock();
         cv.notify_one();
     }
 }
 
 int main(void) {
     thread t1(work, 'A', 10);
     thread t2(work, 'B', 10);
     work('C', 10);
 
     t1.join();
     t2.join();
 
     return 0;
 }

题目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....

 #include <iostream>
 #include <thread>
 #include <mutex>
 #include <fstream>
 #include <condition_variable>
 using namespace std;
 
 const string filename = "D://code//c++//ac36";
 condition_variable cv;
 std::mutex mtex;
 
 int vis[] = {4, 1, 2, 3};//四个文件上一次分别写入的值
 
 ofstream f1(filename + "_A.txt");
 ofstream f2(filename + "_B.txt");
 ofstream f3(filename + "_C.txt");
 ofstream f4(filename + "_D.txt");
 
 ofstream *file[4];
     
 void solve(const int x, int gg) {
     while(gg--){
         for(int i = 0; i < 4; ++i) {
 
             std::unique_lock<std::mutex> lk(mtex);
 
             if(x == 1) {
                 cv.wait(lk, [&]{
                     return vis[i] == 4;
                 });
                 (*file[i]) << 1;
                 vis[i] = 1;
                 lk.unlock();
                 cv.notify_all();
             }else if(x == 2) {
                 cv.wait(lk, [&]{
                     return vis[i] == 1;
                 });
                 (*file[i]) << 2;
                 vis[i] = 2;
                 lk.unlock();
                 cv.notify_all();
             }else if(x == 3) {
                 cv.wait(lk, [&]{
                     return vis[i] == 2;
                 });
                 (*file[i]) << 3; 
                 vis[i] = 3;
                 lk.unlock();
                 cv.notify_all();
             }else {
                 cv.wait(lk, [&]{
                     return vis[i] == 3;
                 });
                 (*file[i]) << 4;
                 vis[i] = 4;
                 lk.unlock();
                 cv.notify_all();
             }
         }
     }
 }
 
 int main(void) {
     file[0] = &f1;
     file[1] = &f2;
     file[2] = &f3;
     file[3] = &f4;
 
     thread t1(solve, 1, 10);
     thread t2(solve, 2, 10);
     thread t3(solve, 3, 10);
     solve(4, 10);
 
     t1.join();
     t2.join();
     t3.join();
 
     for(int i = 0; i < 4; ++i) {
         file[i]->close();
     }
     return 0;
 }

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

代码:

#include <iostream>
#include <thread>
#include <mutex>
#include <fstream>
#include <stdio.h>
#include <condition_variable>
using namespace std;

const string filename = "D://code//c++//ac36.txt";
std::condition_variable cv;
std::mutex mtx;
int cnt = 0;

ifstream in(filename);
ofstream out(filename, ios::app);

void write() {
    char ch;
    while(true) {
        std::unique_lock<std::mutex> lk(mtx);
        ch = getchar();
        out << ch;
        ++cnt;
        lk.unlock();
        cv.notify_all();
    }
}

void read() {
    char ch;
    while(true) {
        std::unique_lock<std::mutex> lk(mtx);
        cv.wait(lk, [&]{
            return cnt > 0;
        });
        in >> ch;
        cout << "cout: " << ch << endl;
        --cnt;
    }
}

int main(void) {
    cnt = in.tellg();

    std::thread tw(write);
    std::thread tr1(read);
    std::thread tr2(read);
    std::thread tr3(read);

    tw.join();
    tr1.join();
    tr2.join();
    tr3.join();

    in.close();
    out.close();

    return 0;
}

线程安全的 queue

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

 #include <iostream>
 #include <thread>
 #include <mutex>
 #include <queue>
 #include <chrono>
 #include <condition_variable>
 using namespace std;
 
 template <typename T>
 class thread_safe_queue{
 private:
     std::condition_variable cv;
     std::queue<T> que;
     std::mutex mtx;
 
 public:
     thread_safe_queue() = default;
     thread_safe_queue(const std::queue<T> q) : que(q) {}
     thread_safe_queue(const thread_safe_queue &tsf) {
         std::unique_lock<std::mutex> lk(mtx);
         que = tsf.que;
     }
     ~thread_safe_queue() = default;
 
     void push(const T &value) {
         std::unique_lock<std::mutex> lk(mtx);
         que.push(value);
         lk.unlock();
         cv.notify_all();
     }
 
     T pop(void) {
         std::unique_lock<std::mutex> lk(mtx);
         cv.wait(lk, [&]{
             return bool(!que.empty());
         });
         T value = que.front();
         que.pop();
         return value;
     }
 
     bool empty(void) {
         std::unique_lock<std::mutex> lk(mtx);
         return que.empty();
     }
 };
 
 thread_safe_queue<int> q;
 std::mutex mtx;
 
 int main(void) {
 
     auto push_value = [&]{
         for(int i = 0; i < 100; ++i) {
             q.push(i);
             std::this_thread::sleep_for(std::chrono::seconds(1));
         }
     };
 
     auto pop_value = [&]{
         while(1) {
             while(!q.empty()) {
                 std::unique_lock<std::mutex> lk(mtx);
                 cout << q.pop() << '\n';
             }
         }
     };
 
     thread push_thread1(push_value);
     thread pop_thread1(pop_value);
     thread pop_thread2(pop_value);
     thread pop_thread3(pop_value);
 
     push_thread1.join();
     pop_thread1.join();
     pop_thread2.join();
     pop_thread3.join();
 
     return 0;
 }

题目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:

 #include <iostream>
 #include <thread>
 #include <mutex>
 #include <condition_variable>
 using namespace std;
 
 std::condition_variable cv;
 std::mutex metx;
 int g_Flag = 0;
 int cnt = 0;
 bool flag = false;
 
 int main(void) {
     thread t1([&]{
         std::unique_lock<std::mutex> lk(metx);
         cout << "this is thread1\n";
         g_Flag = 1;
         ++cnt;
         cv.wait(lk, [&]{{
             return flag;
         }});
         cout << "thread1 exit\n";
     });
 
     thread t2([&]{
         std::unique_lock<std::mutex> lk(metx);
         cout << "this is thread2\n";
         g_Flag = 2;
         cnt++;
         flag = true;
         cv.notify_all();
         cout << "thread2 exit\n";
     });
 
     t1.detach();//分离线程
     t2.detach();
 
     std::unique_lock<std::mutex> lc(metx);
     cv.wait(lc, [&]{
         return cnt >= 2;
     });
     cout << "main thread exit\n";
 
     return 0;
 }
 #include <iostream>
 #include <thread>
 #include <mutex>
 #include <atomic>
 #include <future>
 using namespace std;
 
 atomic<int> g_Flag(0), cnt(0);
 
 void thread1(std::future<int> fu) {
     cout << "this is thread1\n";
     g_Flag = 1;
     ++cnt;
     fu.get();//线程1阻塞至线程2设置共享状态, get等待异步操作结束并返回结果
     cout << "thread1 exit\n";
 }
 
 void thread2(std::promise<int> pro) {
     cout << "this is thread2\n";
     g_Flag = 2;
     ++cnt;
     cout << "thread2 exit\n";
     pro.set_value(1);//设置共享值
 }
 
 int main(void) {
     std::promise<int> prom;//创建一个promise对象
     std::future<int> fu = prom.get_future();//获得promise内部的future,fut将和prom共享prom中的共享状态
 
     std::thread t1(thread1, std::move(fu));//通过fut在线程1中得到线程2的状态
     std::thread t2(thread2, std::move(prom));//通过prom设置线程2中的共享状态
 
     t1.detach();
     t2.detach();
 
     while(cnt < 2);
     cout << "main thread exit\n";
 
     return 0;
 }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘大望

谢谢你请的咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值