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

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

mutex m;//保护条件的互斥访问
condition_variable cond;//条件变量
int flag = 10;//条件
void fun(int num) {for (int i = 0; i<50; i++) {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.  while (flag != num)cond.wait(lk);//在调用wait时会执行lk.unlock()  for (int j = 0; j<num; j++)cout << j << " ";cout << endl;flag = (num == 10) ? 100 : 10;cond.notify_one();//被阻塞的线程唤醒后lk.lock()恢复在调用wait前的状态
    }
}
int main() {thread child(fun, 10);fun(100);child.join();system("pause");return 0;
}

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

mutex m;
condition_variable cond;
int loop = 10;
int flag = 0;void func(int id)
{for (int i = 0; i < loop; ++i){unique_lock<mutex> lk(m);while (flag != id)cond.wait(lk);cout << static_cast<char>('A' + id) << " ";flag = (flag + 1) % 3;cond.notify_all();}
}void main()
{thread A(func, 0);thread B(func, 1);func(2);cout << endl;A.join();B.join();system("pause");
}

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

mutex m;
condition_variable cond;
int loop = 10;
int flag;void func(int num)
{for (int i = 0; i < loop; ++i){unique_lock<mutex> lk(m);while (num != flag)cond.wait(lk);cout << num + 1 << " ";flag = (flag + 1) % 4;cond.notify_all();}
}void main(int argc,char *argv[])
{flag = atoi(argv[1]);thread one(func, 1);thread two(func, 2);thread three(func, 3);func(0);one.join();two.join();three.join();cout << endl;system("pause");
}

读者写者问题

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

class rwlock {
private:mutex _lock;condition_variable _wcon, _rcon;unsigned _writer, _reader;int _active;
public:void read_lock() {unique_lock<mutex> lock(_lock);++_reader;while (_active < 0 || _writer > 0)_rcon.wait(lock);--_reader;++_active;}void write_lock() {unique_lock<mutex> lock(_lock);++_writer;while (_active != 0)_wcon.wait(lock);--_writer;_active = -1;}void unlock() {unique_lock<mutex> lock(_lock);if (_active > 0) {--_active;if (_active == 0) _wcon.notify_one();}else {_active = 0;if (_writer > 0) _wcon.notify_one();else if (_reader > 0) _rcon.notify_all();}}rwlock() :_writer(0), _reader(0), _active(0) {}
};void t1(rwlock* rwl) {while (1) {cout << "I want to write." << endl;rwl->write_lock();cout << "writing..." << endl;this_thread::sleep_for(chrono::seconds(5));rwl->unlock();this_thread::sleep_for(chrono::seconds(5));}
}void t2(rwlock* rwl) {while (1) {cout << "t2-I want to read." << endl;rwl->read_lock();cout << "t2-reading..." << endl;this_thread::sleep_for(chrono::seconds(1));rwl->unlock();}
}void t3(rwlock* rwl) {while (1) {cout << "t3-I want to read." << endl;rwl->read_lock();cout << "t3-reading..." << endl;this_thread::sleep_for(chrono::seconds(1));rwl->unlock();}
}int main()
{rwlock* rwl = new rwlock();thread th1(t1, rwl);thread th2(t2, rwl);thread th3(t3, rwl);th1.join();th2.join();th3.join();system("pause");return 0;
}

线程安全的queue

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

template<typename T>
class threadsafe_queue
{
private:mutable std::mutex mut;std::queue<T> data_queue;std::condition_variable data_cond;
public:threadsafe_queue() {}threadsafe_queue(threadsafe_queue const& other){std::lock_guard<std::mutex> lk(other.mut);data_queue = other.data_queue;}void push(T new_value)//入队操作
    {std::lock_guard<std::mutex> lk(mut);data_queue.push(new_value);data_cond.notify_one();}void wait_and_pop(T& value)//直到有元素可以删除为止
    {std::unique_lock<std::mutex> lk(mut);data_cond.wait(lk, [this] {return !data_queue.empty(); });value = data_queue.front();data_queue.pop();}std::shared_ptr<T> wait_and_pop(){std::unique_lock<std::mutex> lk(mut);data_cond.wait(lk, [this] {return !data_queue.empty(); });std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));data_queue.pop();return res;}bool try_pop(T& value)//不管有没有队首元素直接返回
    {std::lock_guard<std::mutex> lk(mut);if (data_queue.empty())return false;value = data_queue.front();data_queue.pop();return true;}std::shared_ptr<T> try_pop(){std::lock_guard<std::mutex> lk(mut);if (data_queue.empty())return std::shared_ptr<T>();std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));data_queue.pop();return res;}bool empty() const{std::lock_guard<std::mutex> lk(mut);return data_queue.empty();}
};

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

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的时候退出

atomic<int> flag(0);void worker1(future<int> fut)
{//线程1  printf("this is thread1\n");flag = 1;fut.get();//线程1阻塞至线程2设置共享状态  get等待异步操作结束并返回结果printf("thread1 exit\n");
}void worker2(promise<int> prom)
{//线程2  printf("this is thread2\n");//C++11的线程输出cout没有boost的好,还是会出现乱序,所以采用printf,有点不爽  flag = 2;prom.set_value(10);//线程2设置了共享状态后,线程1才会被唤醒  printf("thread2 exit\n");
}//利用promise future来控制线程退出的次序
int main()
{promise<int> prom;future<int> fut = prom.get_future();thread one(worker1, move(fut));//注意future和promise不允许拷贝,但是具备move语义
    thread two(worker2, move(prom));while (flag.load() == 0);  ///将本线程从调用线程中分离出来,允许本线程独立执行one.detach();two.detach();//exit(1);//主线程到这里退出  printf("main thread exit\n");system("pause");return 0;
}

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

转载于:https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/5950400.html

c++多线程编程:常见面试题相关推荐

  1. 总结并发编程常见面试题

    Hello,你好呀,我是大白(●-●) 目录标题 并发编程常见面试题 并发编程常见面试题 在Java中守护线程和用户线程的区别? 线程与进程的区别 什么是多线程中的上下文切换 死锁与活锁的区别,死锁与 ...

  2. Java并发编程—常见面试题

    建议: 学习java并发前需要先掌握JVM知识 关于下面问题档案的详细解析都在后面推荐的相关系列文章中 一.线程安全相关 1.什么叫线程安全? 线程安全就是说多线程访问同一代码,不会产生不确定的结果. ...

  3. Linux网络编程常见面试题

    概述 TCP和UDP是网络体系结构TCP/IP模型中传输层一层中的两个不同的通信协议. TCP:传输控制协议,一种面向连接的协议,给用户进程提供可靠的全双工的字节流,TCP套接口是字节流套接口(str ...

  4. 并发编程常见面试题Synchronized 相 关 问 题

    Synchronized 相 关 问 题 问 题 一 : Synchronized 用 过 吗 , 其 原 理 是 什 么? 这 是 一 道 Java 面 试 中 几 乎 百 分 百 会 问 到 的 ...

  5. Java多线程常见面试题及答案汇总1000道(春招+秋招+社招)

    Java多线程面试题以及答案整理[最新版]Java多线程高级面试题大全(2021版),发现网上很多Java多线程面试题都没有答案,所以花了很长时间搜集,本套Java多线程面试题大全,汇总了大量经典的J ...

  6. java多线程常用面试_java的多线程常见面试题

    并行和并发有什么区别? (推荐学习:java常见面试题) 并行是指两个或者多个事件在同一时刻发生:而并发是指两个或多个事件在同一时间间隔发生. 并行是在不同实体上的多个事件,并发是在同一实体上的多个事 ...

  7. iOS 多线程 自动释放池常见面试题代码

    同步:代码依次执行,一个人执行多个任务,也是依次执行.一个人在同一时间只执行一个任务 异步:可以同时执行多个任务 进程:指在系统中运行的应用程序,每个进程都是独立的,都有独立的且安全的运行空间 线程: ...

  8. MySQL数据库常见面试题总结

    1.数据库的常用范式: 第一范式(1NF):指表的列不可再分,数据库中表的每一列都是不可分割的基本数据项,同一列中不能有多个值: 第二范式(2NF):在 1NF 的基础上,还包含两部分的内容:一是表必 ...

  9. 加上项目路径 spring security忽略不生效_Spring 常见面试题「收藏」

    Spring 常见面试题 1 Spring框架是什么?它的主要模块有哪些? Spring框架是一个Java平台,提供全面的基础设施支持开发Java应用程序.Spring处理基础设施部分,这样你就可以专 ...

  10. 总结Java常见面试题和答案

    转载自  总结Java常见面试题和答案 int和Integer有什么区别?   答:int是java的原始数据类型,Integer是java为int提供的封装类,java为每个原始数据类型都提供了封装 ...

最新文章

  1. python matplotlib绘图 axes和pyplot用法的区别是什么?子图subplot
  2. confluence添加用户_玩转Confluence插件开发插件模块配置文件介绍(04)
  3. sicily 1012. Stacking Cylinders
  4. android 弹起键盘把ui顶上去的解决办法
  5. TikZ绘图示例——尺规作图: 圆内接正九边形的近似画法
  6. 2017-2018-2 20155315《网络对抗技术》Exp3:免杀原理与实践
  7. ceph搭建_如何一键搭建并管理Filecoin集群节点 | Gamma OS新功能上线
  8. 雅可比迭代法和高斯赛德尔迭代法
  9. Journal of BitcoinJ 从clone开始
  10. 九宫格日记 2017年12月19日(周二)
  11. 3D打印机之Marlin固件配置
  12. android图案解锁忘了怎么解,安卓手机解锁图案忘了怎么办?手机解锁密码忘了怎么办?...
  13. c语言合数的分解编程,C语言 · 分解质因数
  14. 图书行业的两个术语:实洋、码洋
  15. windows server 2008共享文件夹
  16. html网页制作比赛要求,校园网页设计大赛活动方案
  17. idb 怎么回复mysql_MySql数据库通过idb和frm恢复
  18. 关于先有鸡还是先有蛋,终于有正确答案了 1
  19. ...的Comparator和Compa
  20. 万丈高楼平地起 ——浅谈网格计算基础

热门文章

  1. 大整数减法(超过整型的表示范围)
  2. Android判断当前的android设备是否处于联网状态
  3. ecshop文章增加点击次数插件
  4. Matlab如何从dat或者txt文件读入数据
  5. python isinstance函数判断object的类型
  6. deepspeaker(TensorFlow)百度声纹识别和对比代码和模型
  7. CentOS7.X的系统管理、安全设置及系统优化思路
  8. 交通优化需求下 智能交通已达千亿市场
  9. Citrix XenServer 关键配置文件
  10. Matlab图像处理基本函数(1)