谷歌面试题 多线程的同步与互斥操作

来源:互联网 发布:淘宝阿里旺旺在哪里 编辑:程序博客网 时间:2024/05/22 09:45

题目来源:秒杀多线程第一篇 多线程笔试面试题汇总
/********************************/
第五题(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….

请设计程序。

/********************************/
以下是本人作答部分。

#include "stdio.h"#include <WINDOWS.H>#define BUF_LEN         50#define THREAD_NUM      4#define EVENT_NUM       4char g_ABuf[BUF_LEN] = {0};     //模拟文件 A 下同int  g_ABufTail = 0;char g_BBuf[BUF_LEN] = {0};int  g_BBufTail = 0;char g_CBuf[BUF_LEN] = {0};int  g_CBufTail = 0;char g_DBuf[BUF_LEN] = {0};int  g_DBufTail = 0;/** 0 [0][1][2][3] 第0组用于同步对文件A的写操作,依次类推* 1 [0][1][2][3]* 2 [0][1][2][3]* 3 [0][1][2][3]*/HANDLE g_EventHandle[EVENT_NUM][EVENT_NUM] = {INVALID_HANDLE_VALUE};    //同步四个文件写入操作DWORD  g_dwThreadID[THREAD_NUM] = {0};//线程IDHANDLE  g_ExitThreadHandle = INVALID_HANDLE_VALUE;  //等待退出线程HANDLE  g_ThreadExitHandle[THREAD_NUM] = {INVALID_HANDLE_VALUE};//线程退出,通知主线程DWORD WINAPI ThreadFunc(LPVOID  lparam);void    WriteABuffer(DWORD dwTmp);//文件A写操作 下同void    WriteBBuffer(DWORD dwTmp);void    WriteCBuffer(DWORD dwTmp);void    WriteDBuffer(DWORD dwTmp);CRITICAL_SECTION    g_Critical;void    WriteABuffer(DWORD dwTmp){    //使用临界区对文件A的访问加锁,使多个线程可以互斥访问 下同    EnterCriticalSection(&g_Critical);    if (g_ABufTail >= BUF_LEN)    {        LeaveCriticalSection(&g_Critical);        return ;    }    g_ABuf[g_ABufTail++] = (char)dwTmp + (char)0x31;    Sleep(10);    LeaveCriticalSection(&g_Critical);}void    WriteBBuffer(DWORD dwTmp){    EnterCriticalSection(&g_Critical);    if (g_BBufTail >= BUF_LEN)    {        LeaveCriticalSection(&g_Critical);        return ;    }    g_BBuf[g_BBufTail++] = (char)dwTmp + (char)0x31;    Sleep(20);    LeaveCriticalSection(&g_Critical);}void    WriteCBuffer(DWORD dwTmp){    EnterCriticalSection(&g_Critical);    if (g_CBufTail >= BUF_LEN)    {        LeaveCriticalSection(&g_Critical);        return ;    }    g_CBuf[g_CBufTail++] = (char)dwTmp + (char)0x31;    Sleep(5);    LeaveCriticalSection(&g_Critical);}void    WriteDBuffer(DWORD dwTmp){    EnterCriticalSection(&g_Critical);    if (g_DBufTail >= BUF_LEN)    {        LeaveCriticalSection(&g_Critical);        return ;    }    g_DBuf[g_DBufTail++] = (char)dwTmp + (char)0x31;    Sleep(15);    LeaveCriticalSection(&g_Critical);}DWORD   WINAPI ThreadFunc( LPVOID lparam ){    DWORD ldw_ThreadID = (DWORD)lparam;    DWORD dwRt = 0;    DWORD dwii = 0;    while(1)    {        dwRt = WaitForSingleObject(g_ExitThreadHandle,0);   //等待主线程通知何时退出        if (WAIT_OBJECT_0 == dwRt)        {            break;        }        dwii = (THREAD_NUM + ldw_ThreadID - 1)%THREAD_NUM; //计算需等待的前一个事件对象的下标        dwRt = WaitForSingleObject(g_EventHandle[0][dwii],0);//对于文件A,本线程需等待前一个线程的信号        if (WAIT_OBJECT_0 == dwRt)        {            WriteABuffer(ldw_ThreadID);            SetEvent(g_EventHandle[0][ldw_ThreadID]);//将本线程事件对象设置为有信号状态,以此通知下一个线程对文件A写操作        }        dwRt = WaitForSingleObject(g_EventHandle[1][dwii],0);        if (WAIT_OBJECT_0 == dwRt)        {            WriteBBuffer(ldw_ThreadID);            SetEvent(g_EventHandle[1][ldw_ThreadID]);        }        dwRt = WaitForSingleObject(g_EventHandle[2][dwii],0);        if (WAIT_OBJECT_0 == dwRt)        {            WriteCBuffer(ldw_ThreadID);            SetEvent(g_EventHandle[2][ldw_ThreadID]);        }        dwRt = WaitForSingleObject(g_EventHandle[3][dwii],0);        if (WAIT_OBJECT_0 == dwRt)        {            WriteDBuffer(ldw_ThreadID);            SetEvent(g_EventHandle[3][ldw_ThreadID]);        }    }    SetEvent(g_ThreadExitHandle[ldw_ThreadID]); //通知主线程,本线程已退出    return 0;}int main(){    int ii = 0,jj = 0,kk = 0;    //初始化临界区    InitializeCriticalSection(&g_Critical);    //创建各部分事件对象及线程    g_ExitThreadHandle = CreateEvent(NULL,TRUE,FALSE,NULL);    for (jj = 0; jj < EVENT_NUM;jj++)    {        for(kk = 0; kk < EVENT_NUM;kk++)        g_EventHandle[jj][kk] = CreateEvent(NULL,FALSE,FALSE,NULL);    }    //按需设置事件对象为信号状态    SetEvent(g_EventHandle[0][3]);    SetEvent(g_EventHandle[1][0]);    SetEvent(g_EventHandle[2][1]);    SetEvent(g_EventHandle[3][2]);    HANDLE lh_ThreadHandle = INVALID_HANDLE_VALUE;    for(ii = 0 ; ii < THREAD_NUM;ii++)    {        lh_ThreadHandle = CreateThread(NULL,0,ThreadFunc,(LPVOID)ii,0,&g_dwThreadID[ii]);        if (NULL != lh_ThreadHandle)        {            //释放主线程对内核对象的引用计数            CloseHandle(lh_ThreadHandle);        }        else            return -1;        g_ThreadExitHandle[ii] = CreateEvent(NULL,FALSE,FALSE,NULL);    }    printf("按下回车查看运行结果");    while(getchar() != '\n');//等待按下回车,退出程序    SetEvent(g_ExitThreadHandle);    //wait thread exit and delete critical section    DWORD dwrt = WaitForMultipleObjects(THREAD_NUM,g_ThreadExitHandle,TRUE,INFINITE);    DeleteCriticalSection(&g_Critical);    //清理内核对象的引用计数    CloseHandle(g_ExitThreadHandle);    g_ExitThreadHandle = INVALID_HANDLE_VALUE;    for (jj = 0; jj < EVENT_NUM;jj++)    {        for(kk = 0; kk < EVENT_NUM;kk++)        {            CloseHandle(g_EventHandle[jj][kk]);            g_EventHandle[jj][kk] = INVALID_HANDLE_VALUE;        }    }    for(ii = 0 ; ii < THREAD_NUM;ii++)    {           CloseHandle(g_ThreadExitHandle[ii]);        g_ThreadExitHandle[ii] = INVALID_HANDLE_VALUE;    }    //输出结果    for (ii = 0;ii < g_ABufTail;ii++)    {        putchar(g_ABuf[ii]);    }    putchar('\n');    for (ii = 0;ii < g_BBufTail;ii++)    {        putchar(g_BBuf[ii]);    }    putchar('\n');    for (ii = 0;ii < g_CBufTail;ii++)    {        putchar(g_CBuf[ii]);    }    putchar('\n');    for (ii = 0;ii < g_DBufTail;ii++)    {        putchar(g_DBuf[ii]);    }    putchar('\n');    printf("按下回车退出");    while(getchar() != '\n');    return 0;}
0 0
原创粉丝点击