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

子线程与主线程必有一个满足条件(flag == num),不满足条件的那个线程不可能获取unique_lock(会在wait中释放),只有满足条件的线程才能获取锁,执行程序

  1. mutex m;//保护条件的互斥访问
  2. condition_variable cond;//条件变量
  3. int flag = ;//条件
  4. void fun(int num) {
  5. for (int i = ; i<; i++) {
  6. unique_lock<mutex> lk(m);//A unique lock is an object that manages a mutex object with unique ownership in both states: locked and unlocked.
  7. while (flag != num)
  8. cond.wait(lk);//在调用wait时会执行lk.unlock()
  9. for (int j = ; j<num; j++)
  10. cout << j << " ";
  11. cout << endl;
  12. flag = (num == ) ? : ;
  13. cond.notify_one();//被阻塞的线程唤醒后lk.lock()恢复在调用wait前的状态
  14. }
  15. }
  16. int main() {
  17. thread child(fun, );
  18. fun();
  19. child.join();
  20.  
  21. system("pause");
  22. return ;
  23. }

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

  1. mutex m;
  2. condition_variable cond;
  3. int loop = ;
  4. int flag = ;
  5.  
  6. void func(int id)
  7. {
  8. for (int i = ; i < loop; ++i)
  9. {
  10. unique_lock<mutex> lk(m);
  11. while (flag != id)
  12. cond.wait(lk);
  13. cout << static_cast<char>('A' + id) << " ";
  14. flag = (flag + ) % ;
  15. cond.notify_all();
  16. }
  17. }
  18.  
  19. void main()
  20. {
  21. thread A(func, );
  22. thread B(func, );
  23. func();
  24. cout << endl;
  25.  
  26. A.join();
  27. B.join();
  28.  
  29. system("pause");
  30. }

题目(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. mutex m;
  2. condition_variable cond;
  3. int loop = ;
  4. int flag;
  5.  
  6. void func(int num)
  7. {
  8. for (int i = ; i < loop; ++i)
  9. {
  10. unique_lock<mutex> lk(m);
  11. while (num != flag)
  12. cond.wait(lk);
  13. cout << num + << " ";
  14. flag = (flag + ) % ;
  15. cond.notify_all();
  16. }
  17. }
  18.  
  19. void main(int argc,char *argv[])
  20. {
  21. flag = atoi(argv[]);
  22. thread one(func, );
  23. thread two(func, );
  24. thread three(func, );
  25. func();
  26. one.join();
  27. two.join();
  28. three.join();
  29. cout << endl;
  30.  
  31. system("pause");
  32. }

读者写者问题

这也是一个非常经典的多线程题目,题目大意如下:有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者读时写者也不能写。

  1. class rwlock {
  2. private:
  3. mutex _lock;
  4. condition_variable _wcon, _rcon;
  5. unsigned _writer, _reader;
  6. int _active;
  7. public:
  8. void read_lock() {
  9. unique_lock<mutex> lock(_lock);
  10. ++_reader;
  11. while (_active < || _writer > )
  12. _rcon.wait(lock);
  13. --_reader;
  14. ++_active;
  15. }
  16. void write_lock() {
  17. unique_lock<mutex> lock(_lock);
  18. ++_writer;
  19. while (_active != )
  20. _wcon.wait(lock);
  21. --_writer;
  22. _active = -;
  23. }
  24. void unlock() {
  25. unique_lock<mutex> lock(_lock);
  26. if (_active > ) {
  27. --_active;
  28. if (_active == ) _wcon.notify_one();
  29. }
  30. else {
  31. _active = ;
  32. if (_writer > ) _wcon.notify_one();
  33. else if (_reader > ) _rcon.notify_all();
  34. }
  35.  
  36. }
  37. rwlock() :_writer(), _reader(), _active() {
  38. }
  39. };
  40.  
  41. void t1(rwlock* rwl) {
  42. while () {
  43. cout << "I want to write." << endl;
  44. rwl->write_lock();
  45. cout << "writing..." << endl;
  46. this_thread::sleep_for(chrono::seconds());
  47. rwl->unlock();
  48. this_thread::sleep_for(chrono::seconds());
  49. }
  50. }
  51.  
  52. void t2(rwlock* rwl) {
  53. while () {
  54. cout << "t2-I want to read." << endl;
  55. rwl->read_lock();
  56. cout << "t2-reading..." << endl;
  57. this_thread::sleep_for(chrono::seconds());
  58. rwl->unlock();
  59. }
  60. }
  61.  
  62. void t3(rwlock* rwl) {
  63. while () {
  64. cout << "t3-I want to read." << endl;
  65. rwl->read_lock();
  66. cout << "t3-reading..." << endl;
  67. this_thread::sleep_for(chrono::seconds());
  68. rwl->unlock();
  69. }
  70. }
  71.  
  72. int main()
  73. {
  74. rwlock* rwl = new rwlock();
  75. thread th1(t1, rwl);
  76. thread th2(t2, rwl);
  77. thread th3(t3, rwl);
  78. th1.join();
  79. th2.join();
  80. th3.join();
  81.  
  82. system("pause");
  83. return ;
  84. }

线程安全的queue

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

  1. template<typename T>
  2. class threadsafe_queue
  3. {
  4. private:
  5. mutable std::mutex mut;
  6. std::queue<T> data_queue;
  7. std::condition_variable data_cond;
  8. public:
  9. threadsafe_queue() {}
  10. threadsafe_queue(threadsafe_queue const& other)
  11. {
  12. std::lock_guard<std::mutex> lk(other.mut);
  13. data_queue = other.data_queue;
  14. }
  15. void push(T new_value)//入队操作
  16. {
  17. std::lock_guard<std::mutex> lk(mut);
  18. data_queue.push(new_value);
  19. data_cond.notify_one();
  20. }
  21. void wait_and_pop(T& value)//直到有元素可以删除为止
  22. {
  23. std::unique_lock<std::mutex> lk(mut);
  24. data_cond.wait(lk, [this] {return !data_queue.empty(); });
  25. value = data_queue.front();
  26. data_queue.pop();
  27. }
  28. std::shared_ptr<T> wait_and_pop()
  29. {
  30. std::unique_lock<std::mutex> lk(mut);
  31. data_cond.wait(lk, [this] {return !data_queue.empty(); });
  32. std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
  33. data_queue.pop();
  34. return res;
  35. }
  36. bool try_pop(T& value)//不管有没有队首元素直接返回
  37. {
  38. std::lock_guard<std::mutex> lk(mut);
  39. if (data_queue.empty())
  40. return false;
  41. value = data_queue.front();
  42. data_queue.pop();
  43. return true;
  44. }
  45. std::shared_ptr<T> try_pop()
  46. {
  47. std::lock_guard<std::mutex> lk(mut);
  48. if (data_queue.empty())
  49. return std::shared_ptr<T>();
  50. std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
  51. data_queue.pop();
  52. return res;
  53. }
  54. bool empty() const
  55. {
  56. std::lock_guard<std::mutex> lk(mut);
  57. return data_queue.empty();
  58. }
  59. };

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

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. atomic<int> flag();
  2.  
  3. void worker1(future<int> fut)
  4. {//线程1
  5. printf("this is thread1\n");
  6. flag = ;
  7. fut.get();//线程1阻塞至线程2设置共享状态 get等待异步操作结束并返回结果
  8. printf("thread1 exit\n");
  9. }
  10.  
  11. void worker2(promise<int> prom)
  12. {//线程2
  13. printf("this is thread2\n");//C++11的线程输出cout没有boost的好,还是会出现乱序,所以采用printf,有点不爽
  14. flag = ;
  15. prom.set_value();//线程2设置了共享状态后,线程1才会被唤醒
  16. printf("thread2 exit\n");
  17. }
  18.  
  19. //利用promise future来控制线程退出的次序
  20. int main()
  21. {
  22. promise<int> prom;
  23. future<int> fut = prom.get_future();
  24. thread one(worker1, move(fut));//注意future和promise不允许拷贝,但是具备move语义
  25. thread two(worker2, move(prom));
  26. while (flag.load() == );
      ///将本线程从调用线程中分离出来,允许本线程独立执行
  27. one.detach();
  28. two.detach();
  29. //exit(1);//主线程到这里退出
  30. printf("main thread exit\n");
  31.  
  32. system("pause");
  33. return ;
  34. }

http://blog.csdn.net/liuxuejiang158blog/article/details/22300081

c++多线程编程:常见面试题的更多相关文章

  1. 整理的最全 python常见面试题(基本必考)

    整理的最全 python常见面试题(基本必考) python 2018-05-17 作者 大蛇王 1.大数据的文件读取 ① 利用生成器generator ②迭代器进行迭代遍历:for line in ...

  2. 整理的最全 python常见面试题

      整理的最全 python常见面试题(基本必考)① ②③④⑤⑥⑦⑧⑨⑩ 1.大数据的文件读取: ① 利用生成器generator: ②迭代器进行迭代遍历:for line in file; 2.迭代 ...

  3. 【转载】JAVA常见面试题及解答(精华)

     JAVA常见面试题及解答(精华)       1)transient和volatile是java关键字吗?(瞬联) 如果用transient声明一个实例变量,当对象存储时,它的值不需要维持.例如: ...

  4. 【javascript常见面试题】常见前端面试题及答案

    转自:http://www.cnblogs.com/syfwhu/p/4434132.html 前言 本文是在GitHub上看到一个大牛总结的前端常见面试题,很多问题问的都很好,很经典.很有代表性.上 ...

  5. 夯实Java基础系列16:一文读懂Java IO流和常见面试题

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  6. 【搞定 Java 并发面试】面试最常问的 Java 并发基础常见面试题总结!

    本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.欢迎 Sta ...

  7. 【搞定 Java 并发面试】面试最常问的 Java 并发进阶常见面试题总结!

    本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.觉得内容不错 ...

  8. Java面试炼金系列 (1) | 关于String类的常见面试题剖析

    Java面试炼金系列 (1) | 关于String类的常见面试题剖析 文章以及源代码已被收录到:https://github.com/mio4/Java-Gold 0x0 基础知识 1. '==' 运 ...

  9. Spring 常见面试题总结 | JavaGuide

    首发于 JavaGuide 在线网站:Spring 常见面试题总结 最近在对 JavaGuide 的内容进行重构完善,同步一下最新更新,希望能够帮助你. Spring 基础 什么是 Spring 框架 ...

  10. java常见面试题及答案 1-10(基础篇)

    java常见面试题及答案 1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程.Java 源文件被 ...

随机推荐

  1. Linux centos7开机界面出现多个选项

    centos7开机界面出现多个选项时 前面几个选项正常启动,最后一个选项急救模式启动(系统出项问题不能正常启动时使用并修复系统) 在CentOS更新后,并不会自动删除旧内核.所以在启动选项中会有多个内 ...

  2. 技术抄录_Java高级架构师教程

    1.B2C商城项目实战     2.高性能架构专题     3.架构筑基与开源框架解析专题     4.团队协作开发专题     5.微服务架构专题     6.设计模式     附上[架构资料]   ...

  3. DELETE - 删除一个表中的行

    SYNOPSIS DELETE FROM [ ONLY ] table [ WHERE condition ] DESCRIPTION 描述 DELETE 从指明的表里删除满足 WHERE 子句的行. ...

  4. 如何移除不再插入Windows设备的信息

    Howto: Remove devices from Windows that are not connected to the system anymore 如何移除不再插入Windows设备的信息 ...

  5. ORA-03113: end-of-file on & ORA-07445

    --------------ORA-03113: end-of-file on-------------- SQL> show parameter background_dump; NAME T ...

  6. BZOJ3940: [Usaco2015 Feb]Censoring (AC自动机)

    题意:在文本串上删除一些字符串 每次优先删除从左边开始第一个满足的 删除后剩下的串连在一起重复删除步骤 直到不能删 题解:建fail 用栈存当前放进了那些字符 如果可以删 fail指针跳到前面去 好菜 ...

  7. git-忽略文件改动不进行提交

    命令:git update-index --assume-unchanged 文件名 作用:忽略文件的改动,但是不加入.gitignore 文件中,这样可以达到仅在本地目录中忽略,不影响其他团队成员的 ...

  8. Informatica抽取SQL Server数据库乱码

    1.首先确认数据库的关系连接所使用的代码页,是否一致 2.如果上述方法不行,在Designer中更改数据类型,将string类型改为nstring类型,中文就没有乱码了 3.SQL Server数据库 ...

  9. Linux启动流程CentOS6和7的区别

    目 录 Linux启动流程    I 第1章 CentOS6启动流程    1 1.1 BIOS    1 1.2 MBR    1 1.3 GRUB    1 1.4 kernel(加载内核)    ...

  10. php函数之数组

    关联数组 isset bool isset( mixed $val [, mix $...]) 变量是否已设置并且非null.多个参数从左到右计算. 判断null $a=null;var_dump(i ...