面试题中的多线程

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


从图中们可以看到,主线程的执行每次都依赖于子线程,只有子线程执行完才执行主线程.
一个线程依赖于另一个线程的实现,那就是同步.
使用event或者semaphore实现:

我用event实现,比较简单.

#include <iostream>
#include <windows.h>
#include <process.h>

int g_count = 10;

HANDLE g_ThreadEventSon ,g_ThreadEventFather, g_threadMutex,g_threadSemaphore ;

unsigned int __stdcall ThreadFun(void *pthread_num)
{
    for ( int i=0 ; i<g_count ;++ i ){
        WaitForSingleObject(g_ThreadEventFather ,INFINITE);
        std::cout <<"子线程开始循环\n";
        for ( int j =0; j<10; ++ j ){
            std::cout <<j<< " ";
        }
        std::cout <<std::endl;
        SetEvent(g_ThreadEventSon );
    }
    return 0;
}

int main ()
{
    g_ThreadEventSon = CreateEvent(NULL ,false,false,NULL);
    g_ThreadEventFather = CreateEvent(NULL ,false,true,NULL);

    HANDLE h =(HANDLE ) _beginthreadex( NULL,0,ThreadFun ,NULL,0, NULL);

    for ( int i=0 ; i<g_count ;++ i ){
        WaitForSingleObject(g_ThreadEventSon ,INFINITE);
        std::cout <<"主线程开始循环\n";
        for ( int j =0; j<100; ++ j ){
            std::cout <<j<< " ";
        }
        std::cout <<std::endl;
        SetEvent(g_ThreadEventFather );
    }

    CloseHandle( g_ThreadEventFather);
    CloseHandle( g_ThreadEventSon);
    return 0;
}



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

创建3个线程依次打印ABC用同步方法道理一样,不再赘述.

方法1:用event实现:(同步)
#include <iostream>
#include <windows.h>
#include <process.h>

int g_count = 10;

HANDLE g_Event_A ,g_Event_B, g_Event_C;

unsigned int __stdcall ThreadFunA(void *pthread_num)
{
    for ( int i=0 ; i<g_count ;++ i ){
        WaitForSingleObject(g_Event_A ,INFINITE);
        
        std::cout <<"A";
        SetEvent(g_Event_B );
    }

                 return 0;
}
unsigned int __stdcall ThreadFunC(void *pthread_num)
{
    for ( int i=0 ; i<g_count ;++ i ){
        WaitForSingleObject(g_Event_C ,INFINITE);
        std::cout <<"C";
        SetEvent(g_Event_A );
    }

    return 0;
}
unsigned int __stdcall ThreadFunB(void *pthread_num)
{
    for ( int i=0 ; i<g_count ;++ i ){
        WaitForSingleObject(g_Event_B ,INFINITE);

        std::cout <<"B";
        SetEvent(g_Event_C );
    }

    return 0;
}

int main ()
{
    g_Event_A = CreateEvent(NULL ,false,true,NULL);
    g_Event_B = CreateEvent(NULL ,false,false,NULL);
    g_Event_C = CreateEvent(NULL ,false,false,NULL);

    HANDLE h[3];
    h[0] =( HANDLE) _beginthreadex (NULL,0, ThreadFunA,NULL ,0,NULL);
    h[1] =( HANDLE) _beginthreadex (NULL,0, ThreadFunB,NULL ,0,NULL);
    h[2] =( HANDLE) _beginthreadex (NULL,0, ThreadFunC,NULL ,0,NULL);

    WaitForMultipleObjects(3, h,true ,INFINITE);
    CloseHandle( g_Event_A);
    CloseHandle( g_Event_B);
    CloseHandle( g_Event_C);
  

    return 0;
}

方法2:用临界区实现(互斥)
使用临界区的核心思想在于,每个线程进入临界区后判断是不是该他输出了,轮到他输出就输出,否则退出临界区.

#include <iostream>
#include <windows.h>
#include <process.h>

int g_count = 10;
int g_num = 0;
int g_curr = 0;

CRITICAL_SECTION g_critical_section;
unsigned int __stdcall ThreadFun (void * pthread_num)
{
    char ID;
    int num;
    int loop = 0;
    EnterCriticalSection(& g_critical_section );
    ID = g_num+ 'A';
    num = g_num++;
    LeaveCriticalSection(& g_critical_section );

    while ( loop <10 ){
        EnterCriticalSection (&g_critical_section );
        if ( num == g_curr ){
            std ::cout << ID;
            loop ++;
            g_curr = ++g_curr %3;
        }
        LeaveCriticalSection (&g_critical_section );
    }
  


    return 0;
}
int main ()
{
   InitializeCriticalSection(& g_critical_section );
   HANDLE h [3];
   for ( int i=0 ; i<3; ++ i ){
       h [i ] =( HANDLE) _beginthreadex (NULL ,0, ThreadFun, NULL ,0,NULL );
   }
 
   WaitForMultipleObjects(3, h ,true , INFINITE);
    return 0;
}

有四个线程1、234。线程1的功能就是输出1,线程2的功能就是输出2,以此类推.........现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式:

A1 2 3 4 1 2....

B2 3 4 1 2 3....

C3 4 1 2 3 4....

D4 1 2 3 4 1....

请设计程序。

请设计程序。
核心思想和上一个用临界区实现方法一样.
临界区方法实现:
#include <iostream>
#include <windows.h>
#include <process.h>

int g_count = 10;
int g_num = 0;
int fileNum [4];
CRITICAL_SECTION g_critical_section;
unsigned int __stdcall ThreadFun (void * pthread_num)
{
    int num;
    int loop = 0;
    int fileCount[4];
    for ( int i=0; i<4; ++ i ){
        fileCount [i ] = 0;
    }
    EnterCriticalSection(& g_critical_section );
    num = g_num++;
    LeaveCriticalSection(& g_critical_section );

    while ( loop <12 ){
        EnterCriticalSection (&g_critical_section );
        for ( int i=0; i<4; ++ i ){
            if ( fileNum [ i] == num && fileCount [i ]<3){
                fileNum [i ] = ( fileNum[ i ]+1)%4;
                fileCount [i ]++;
                std ::cout <<( char)( 'A' + i )<< ":" << num +1<< std :: endl;
                loop ++;
            }
        }
        LeaveCriticalSection (&g_critical_section );
    }
    return 0;
}
int main ()
{
    for ( int i=0; i<4 ; ++ i ){
        fileNum [i ] = i;
    }
    InitializeCriticalSection(& g_critical_section );
    HANDLE h [4];
    for ( int i=0 ; i<4; ++ i ){
        h [i ] =( HANDLE) _beginthreadex (NULL ,0, ThreadFun, NULL ,0,NULL );
    }
    WaitForMultipleObjects(4, h ,true , INFINITE);
    return 0;
}
  

分析结果:
我们看一下开头和结尾就好了,中间数据不必关心.
文件我用ABCD替代,线程我用1,2,3,4替代,例如A:1表示线程1向文件A写入1.
现在我们来分析一下结果:
对于A:从1开始,以4结尾,中间总是1,2,3,4的循环符合要求.
对于B:以2开始,以1结尾,中间总是23412341的循环
对于c和d类似,不在分析
结果满足要求.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值