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 源文件被 ...
随机推荐
- how to use Hexo
Hexo is a good tool to build a personal blog.Here are some good reference:1: https://hexo.io/zh-cn/d ...
- python基础一 day2 数据类型
int: bool: 类型转换: str到int有条件,str必须是数字, "123e"是错误的 bool转换为int类型,需要int(x) 结果: 结果: 空字 ...
- Ioc 之 Unity的依赖注入
Unity是微软官方提供的一个Ioc容器,用来实现依赖注入,减少代码之间的耦合程度.使用Unity实现Ioc方式有两种,一种是使用代码方式实现,一种是利用配置文件来实现. 我们先来看一下代码方式是如何 ...
- 基于Ubuntu 14.04 LTS编译Android4.4.2源代码
转载自:雨水:http://blog.csdn.net/gobitan/article/details/24367439 基于Ubuntu 14.04 LTS编译Android4.4.2源代码 ...
- 雷林鹏分享:Lua 数据类型
Lua是动态类型语言,变量不要类型定义,只需要为变量赋值. 值可以存储在变量中,作为参数传递或结果返回. Lua中有8个基本类型分别为:nil.boolean.number.string.userda ...
- net core 使用ef生成实体类(SqlServer)
1)打开程序包管理器控制台 2)输入命令 Install-Package Microsoft.EntityFrameworkCore.SqlServer 3)输入命令 Install-Packag ...
- SQL Server 2008 阻止保存要求重新创建表的更改
取消[阻止保存要求重新创建表的更改]复选框
- 分享点干货(此this非彼this)this的详细解读
在javascript编程中,this关键字经常让初学者感到迷惑,这里,针对此this根据查阅的资料和个人的理解分享一下,纯手打,大神勿喷. 首先先说一下this的指向,大致可以分为以下四种. 1.作 ...
- 洛谷P2802 回家
贱呼呼的搜索题 这个最贱的还是在于路途的标记,大部分的题目路途的标记是直接标记即可也就是说我走过了这个点,那么这个点标记上以后不再走,这个题不是,我走过了,但是我可能回了血我又继续走 所以说我们标记的 ...
- POJ-1190 蛋糕问题
这道题目我们使用深搜加剪枝的方法来写,我们首先算出一个最小表面积和最小体积来,就是半径从一递增,高度也从一递增,这是题目要求. 然后我们计算出一个底层最大的半径和最大的高度,我们就从这个最大半径和最大 ...