C++11多线程编程(常见面试题)

2019/08/14 11:02
阅读数 30

【题目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();
}
View Code

 

【总结】

理解这段代码的时候,被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();
}
View Code

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部