多线程google面试题

博客围绕一个google面试题展开,有四个线程分别输出1 - 4,要让四个文件A、B、C、D呈现特定格式内容。问题关键在于线程间同步,每次循环向不同文件写字符。利用C++11的条件变量实现该要求,并给出了具体代码和运行结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有四个线程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…

问题分析:

由于每个线程都固定输出一个字符,这个是不会发生变化的,要想达到预期效果,只能是每次循环向不同的文件写字符。这里考察的是线程间同步问题,线程1完成后,才会开始线程2,以此类推。

为了方便分析,我们将题目要求的格式进行转换,给出每次循环每个线程写入的目标文件,格式如下:

在这里插入图片描述
可以分析出,下一轮循环写入的文件有如下格式:

static char szFileName[4][32] ={
        "A.txt",
        "B.txt",
        "C.txt",
        "D.txt"
};

NextLoopFile([i+1) % 4] = CurrentFile[i]

我们利用C++11中提供的条件变量完成完成题目要求:

具体代码如下:

#include <thread>
#include <fstream>
#include <condition_variable>
#include <mutex>

std::condition_variable g_cvWriter;
std::mutex                      g_mutex_writer;
const unsigned  MAX_THREAD_NUM = 4;
const unsigned  MAX_LOOP_NUM = 10;
//控制线程执行流程
unsigned  g_nNextThreadID = 0;
//每一轮的文件ID
unsigned g_nCurrentFileIndex[MAX_THREAD_NUM] = { 0, 1, 2, 3};

//文件名
char g_szFileName[MAX_THREAD_NUM][32] = {
    "A.txt",
    "B.txt",
    "C.txt",
    "D.txt"
};

//每个线程输出的字符
char GetChar(unsigned nID)
{
    return nID + '1';
}

// 每一轮的文件ID
void  GetNextLoopFileIndex()
{
    unsigned nNewLoopFileName[MAX_THREAD_NUM] = { 0 };
    //C[i] = N[(i+1)%max_num]
    for (int i = 0; i < MAX_THREAD_NUM; i++)
    {
        nNewLoopFileName[(i + 1) % MAX_THREAD_NUM] = g_nCurrentFileIndex[i];
    }

    memcpy(g_nCurrentFileIndex, nNewLoopFileName, sizeof(nNewLoopFileName));
}

char* GetFileName(unsigned nID)
{
    return g_szFileName[g_nCurrentFileIndex[nID]];
}

void WriterChar2File(const char* szFileName, char ch)
{
     std::fstream file(szFileName, std::ostream::out | std::ostream::app);
     file << ch;
     file << std::endl;
}

 //nID从 0 1 2 3
void WriterCharThread(unsigned nID)
{
     for (int i = 0; i < MAX_LOOP_NUM; i++)
     {
         std::unique_lock<std::mutex> lk(g_mutex_writer);
         //线程同步
         g_cvWriter.wait(lk, [=](){ return nID == g_nNextThreadID; });

         char ch = GetChar(nID);
         const char* pszFileName = GetFileName(nID);
         WriterChar2File(pszFileName, ch);
         g_nNextThreadID++;

         //新一轮的开始
         if (nID + 1 == MAX_THREAD_NUM)
         {
             GetNextLoopFileIndex();
             g_nNextThreadID = 0;
         }
         //唤醒所有被挂起的线程,同时检查是否满足条件 ,满足条件的会继续执行
         g_cvWriter.notify_all();
     }
}

void main_thread()
{
    std::thread arrThread[MAX_THREAD_NUM];
    for (unsigned i = 0; i < MAX_THREAD_NUM; i++)
    {
        arrThread[i] = std::thread(WriterCharThread, i);
    }

    for (int i = 0; i < MAX_THREAD_NUM; i++)
    {
        arrThread[i].join();
    }
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值