c++多线程编程:常见面试题
题目:子线程循环 10 次,接着主线程循环 100 次,接着又回到子线程循环 10 次,接着再回到主线程又循环 100 次,如此循环50次,试写出代码
子线程与主线程必有一个满足条件(flag == num),不满足条件的那个线程不可能获取unique_lock(会在wait中释放),只有满足条件的线程才能获取锁,执行程序
mutex m;//保护条件的互斥访问
condition_variable cond;//条件变量
int flag = ;//条件
void fun(int num) {
for (int i = ; i<; 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 = ; j<num; j++)
cout << j << " ";
cout << endl;
flag = (num == ) ? : ;
cond.notify_one();//被阻塞的线程唤醒后lk.lock()恢复在调用wait前的状态
}
}
int main() {
thread child(fun, );
fun();
child.join(); system("pause");
return ;
}
题目:编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。
mutex m;
condition_variable cond;
int loop = ;
int flag = ; void func(int id)
{
for (int i = ; i < loop; ++i)
{
unique_lock<mutex> lk(m);
while (flag != id)
cond.wait(lk);
cout << static_cast<char>('A' + id) << " ";
flag = (flag + ) % ;
cond.notify_all();
}
} void main()
{
thread A(func, );
thread B(func, );
func();
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 = ;
int flag; void func(int num)
{
for (int i = ; i < loop; ++i)
{
unique_lock<mutex> lk(m);
while (num != flag)
cond.wait(lk);
cout << num + << " ";
flag = (flag + ) % ;
cond.notify_all();
}
} void main(int argc,char *argv[])
{
flag = atoi(argv[]);
thread one(func, );
thread two(func, );
thread three(func, );
func();
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 < || _writer > )
_rcon.wait(lock);
--_reader;
++_active;
}
void write_lock() {
unique_lock<mutex> lock(_lock);
++_writer;
while (_active != )
_wcon.wait(lock);
--_writer;
_active = -;
}
void unlock() {
unique_lock<mutex> lock(_lock);
if (_active > ) {
--_active;
if (_active == ) _wcon.notify_one();
}
else {
_active = ;
if (_writer > ) _wcon.notify_one();
else if (_reader > ) _rcon.notify_all();
} }
rwlock() :_writer(), _reader(), _active() {
}
}; void t1(rwlock* rwl) {
while () {
cout << "I want to write." << endl;
rwl->write_lock();
cout << "writing..." << endl;
this_thread::sleep_for(chrono::seconds());
rwl->unlock();
this_thread::sleep_for(chrono::seconds());
}
} void t2(rwlock* rwl) {
while () {
cout << "t2-I want to read." << endl;
rwl->read_lock();
cout << "t2-reading..." << endl;
this_thread::sleep_for(chrono::seconds());
rwl->unlock();
}
} void t3(rwlock* rwl) {
while () {
cout << "t3-I want to read." << endl;
rwl->read_lock();
cout << "t3-reading..." << endl;
this_thread::sleep_for(chrono::seconds());
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 ;
}
线程安全的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(); void worker1(future<int> fut)
{//线程1
printf("this is thread1\n");
flag = ;
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 = ;
prom.set_value();//线程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() == );
///将本线程从调用线程中分离出来,允许本线程独立执行
one.detach();
two.detach();
//exit(1);//主线程到这里退出
printf("main thread exit\n"); system("pause");
return ;
}
http://blog.csdn.net/liuxuejiang158blog/article/details/22300081
c++多线程编程:常见面试题的更多相关文章
- 整理的最全 python常见面试题(基本必考)
整理的最全 python常见面试题(基本必考) python 2018-05-17 作者 大蛇王 1.大数据的文件读取 ① 利用生成器generator ②迭代器进行迭代遍历:for line in ...
- 整理的最全 python常见面试题
整理的最全 python常见面试题(基本必考)① ②③④⑤⑥⑦⑧⑨⑩ 1.大数据的文件读取: ① 利用生成器generator: ②迭代器进行迭代遍历:for line in file; 2.迭代 ...
- 【转载】JAVA常见面试题及解答(精华)
JAVA常见面试题及解答(精华) 1)transient和volatile是java关键字吗?(瞬联) 如果用transient声明一个实例变量,当对象存储时,它的值不需要维持.例如: ...
- 【javascript常见面试题】常见前端面试题及答案
转自:http://www.cnblogs.com/syfwhu/p/4434132.html 前言 本文是在GitHub上看到一个大牛总结的前端常见面试题,很多问题问的都很好,很经典.很有代表性.上 ...
- 夯实Java基础系列16:一文读懂Java IO流和常见面试题
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- 【搞定 Java 并发面试】面试最常问的 Java 并发基础常见面试题总结!
本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.欢迎 Sta ...
- 【搞定 Java 并发面试】面试最常问的 Java 并发进阶常见面试题总结!
本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.觉得内容不错 ...
- Java面试炼金系列 (1) | 关于String类的常见面试题剖析
Java面试炼金系列 (1) | 关于String类的常见面试题剖析 文章以及源代码已被收录到:https://github.com/mio4/Java-Gold 0x0 基础知识 1. '==' 运 ...
- Spring 常见面试题总结 | JavaGuide
首发于 JavaGuide 在线网站:Spring 常见面试题总结 最近在对 JavaGuide 的内容进行重构完善,同步一下最新更新,希望能够帮助你. Spring 基础 什么是 Spring 框架 ...
- java常见面试题及答案 1-10(基础篇)
java常见面试题及答案 1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程.Java 源文件被 ...
随机推荐
- Python 使用re模块实现正则表达式
# coding: utf-8 # Team : Quality Management Center # Author:Carson # Date :2019/6/21 10:41 # Tool :P ...
- Windows API函数大全(完整)
Windows API函数大全,从事软件开发的朋友可以参考下 1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一 ...
- 转--C#编程总结
C#编程总结--总目录 http://www.cnblogs.com/yank/p/3543423.html
- dpdk快速编译使用
QuickStart 环境 dpdk: dpdk-17.11 运行前配置 配置系统HugePages #mkdir /mnt/huge_1GB/ #vim /etc/fstab nodev /mnt/ ...
- 前端学习日记-vue cli3.0环境搭建
卸载老版本的 vue-cli : npm uninstall vue-cli -g 安装新版本的 : npm install -g @vue/cli --安装新版本cli 同时nodeJS 要更新至 ...
- <Spring Cloud>入门四 Feign
1.Feign 之前使用的是Ribbon+RestTemplate调用,通过的是微服务的名字进行调用,实现负载均衡 但是为了满足接口编程,提供了Feign 2.实现 2.1引入坐标 在 ms-comm ...
- fork 和 exec
https://blog.csdn.net/disadministrator/article/details/39347333 进程创建方法:fork.exec.clone,父进程等待子进程结束是用w ...
- 前端基础之JavaScript_2
摘要: window对象 BOM(Browser Object Model) DOM (Document Object Model) 0.引子: JavaScript分为三部分:ECMAScript. ...
- UI进阶 XML解析适配 'libxml/tree.h'file not found 错误解决办法
Xcode 'libxml/tree.h'file not found 错误解决办法
- [WPF自定义控件]Window(窗体)的UI元素及行为
1. 前言 本来打算写一篇<自定义Window>的文章,但写着写着发觉内容太多,所以还是把使用WindowChrome自定义Window需要用到的部分基础知识独立出来,于是就形成了这篇文章 ...