【题目1】

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

【题解】

首先我们来分析一下这道题...(是个刚入门的小白,分析的不好请见谅)

1、由于子线程需要循环10次不受主线程干扰,而主线程需要循环100次不受子线程干扰,所以显然,在他们进入循环的时候需要一个锁把这段循环锁住,不然会导致资源被抢占(此处的资源可以理解为是循环里的cout)。(其实简单来说互斥量是为了保证子线程和主线程的for不同时进行)

2、然后问题来了,怎么控制子线程循环后主线程循环,然后一直这样依次循环呢?条件变量就可以做到这点,我们可以通过改变某个全局变量的值,第一次将该全局变量置为10,也就是说我们只要控制如果传入的参数和该全局变量不等,就让他一直等待,当执行完子线程的循环后改变这个全局变量为100,那么对于子线程来说全局变量和传入的参数就不相等了,那么条件变量就会一直等待。当然如果一直让他等待肯定是不对的,所以当一个线程执行完循环之后需要唤醒这个条件变量,告诉线程变量已经改变又可以开始抢资源啦。(其实条件变量就是为了控制子主线程运行的先后条件)

【代码】

#include<thread>
#include<iostream>
#include<cstdio>
#include<mutex>
#include<condition_variable>
using namespace std;
int flag = 10;
mutex mu;
condition_variable cv;
void fun(int x, char c)
{
for (int i = 0; i < 50; i++)
{
unique_lock<mutex> lock(mu);
while(flag != x)
cv.wait(lock);//在该线程阻塞之前会执行lock.unlock,这样别的线程才不会被锁住
for (int j = 0; j < x; j++)
cout << c << ":" << j << endl;
flag = (x == 10)? 100 : 10;
cv.notify_one();
}
}
int main()
{
thread t1(fun, 10, 'A');
fun(100, 'B');
t1.join();
}

【总结】

理解这段代码的时候,被wait()弄了好久,可能是我太蠢qwq那么来说一下wait()吧,我们分两种情况来说。

(1)一开始,主线程先抢到了锁

那么就会判断flag是否等于x,很显然如果是主线程先拿到锁此时flag=10,x=100不等,那么这个时候主线程就会执行wait(),也就是会被阻塞,然后因为wait()自身有这样一个机制(当他执行的时候会自动释放锁吗,也就是会自动执行unlock,给其他线程一个拿锁的机会),这个时候子线程就会拿到锁,并且判断fag是否等于x,这时候明显是相等的,那么就会进行下面的一系列循环,这个时候重点来了,一定要改变全局变量!!如果不改变会是什么结果呢?假设我们把那句话注释掉直接执行notify_one(),那么主线程就会被唤醒它的wait()又会自动参与抢锁,由于flag没有改变,那么flag和x的值还是相等,所以它依然会被阻塞,那么依旧就是子线程执行,就不满足题意了。

(2)一开始,子线程先抢到了锁

因为满足flag=x,那么会执行接下来的for,按部就班改个flag,然后唤醒被wait的线程(这时候其实没有),因为执行完一个循环,uniqie_lock会自动释放锁,然后子线程和主线程就又开始抢锁了,这次我们假设还是子线程先抢到了锁,但由于修改了flag,此时flag!=x,子线程就被阻塞,然后就和情况(1)差不多啦。

【题目2】

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

【题解】

其实只要理解了上一题,就是一个套路啦。这里有所不同的是有3个线程,所以最后唤醒条件变量的时候记得用notify_all()。

【代码】

#include<thread>
#include<iostream>
#include<cstdio>
#include<mutex>
#include<condition_variable>
using namespace std;
int flag = 0;
mutex mu;
condition_variable cv;
void fun(int x)
{
for (int i = 0; i < 10; i++)
{
unique_lock<mutex>lock(mu);
while (x != flag)
cv.wait(lock);
cout << static_cast<char>('A' + x) << " ";
flag = (flag + 1) % 3;
cv.notify_all();
}
}
int main()
{
thread t1(fun, 1);
thread t2(fun, 2);
fun(0);
t1.join();
t2.join();
}

C++11多线程编程(常见面试题)的更多相关文章

  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常见面试题及答案 1-10(基础篇)

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

  6. iOS常见面试题汇总

    iOS常见面试题汇总 1. 什么是 ARC? (ARC 是为了解决什么问题而诞生的?) ARC 是 Automatic Reference Counting 的缩写, 即自动引用计数. 这是苹果在 i ...

  7. java常见面试题及答案

    java常见面试题及答案 来源 https://blog.csdn.net/hsk256/article/details/49052293 来源 https://blog.csdn.net/hsk25 ...

  8. Java 常见面试题(一)

    1)什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节码文件.Java被设 ...

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

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

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

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

随机推荐

  1. 云原生系列2 部署你的第一个k8s应用

    云原生的概念和理论体系非常的完备,but talk is cheap , show me the code ! 但是作为一名程序员,能动手的咱绝对不多BB,虽然talk并不cheap , 能跟不同层次 ...

  2. Adobe DreamWeaver CC 快捷键

    1 1 ADOBE DREAMWEAVER CC Shortcuts: DREAMWEAVER CC DOCUMENT EDITING SHORTCUTS Select Dreamweaver > ...

  3. js bitwise operation all in one

    js bitwise operation all in one 位运算 & 按位与 | 按位或 ^ 按位异或 / XOR let a = 5; // 000000000000000000000 ...

  4. JavaScript Number Type Checker

    JavaScript Number Type Checker Number.isInteger // static 方法 Number.isInteger(value) https://develop ...

  5. website text select notes menu

    website text select notes menu website 文字选择笔记菜单(下划线, 标记, 复制, 分享) 下划线, 标记 https://time.geekbang.org/ ...

  6. eui & search select

    eui & search select https://element.eleme.io/#/zh-CN/component/select demo <template> < ...

  7. Datahero Inc利用区块链溯源,造福各行各业

    近些年来,随着区块链技术的不断崛起以及快速发展,越多越多的人提出将区块链技术引入到溯源系统当中,溯源也成为了区块链技术的重要应用场景之一. 目前,Datahero inc已建设一整套的溯源平台系统,基 ...

  8. java初学者必看之构造方法详细解读

    java初学者必看之构造方法详细解读 构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法. 格式 public 类名称(参数类型 参数名称){ 方法体 } 注 ...

  9. [转]ubuntu系统重新分区、根目录扩容

    原文地址:https://blog.csdn.net/code_segment/article/details/79237500,转载主要方便随时查阅,如有版权要求,请及时联系. gparted是一款 ...

  10. ipv4ipv6 地址字符串表示最大长度

    1 for IPV4 #define INET_ADDRSTRLEN 16 111.112.113.114 32位IPV4地址,使用10进制+句点表示时,所占用的char数组的长度为16,其中包括最后 ...