多线程面试题摘选

多线程面试题摘选
一. 概念性问答题

1. 线程的基本概念,线程的基本状态及状态之间的关系?
答:
线程是指在程序执行过程中,能够执行程序代码的一个执行单位,每个程序至少都有一个线程,也就是程序本身。
java线程的基本状态:运行,就绪,挂起,结束。
2. 线程与进程的区别?
答:
     1、 线程是进程的一部分,所以线程有的时候被称为是轻权进程或者轻量级进程。
     2、 一个没有线程的进程是可以被看作单线程的,如果一个进程内拥有多个进程,进程的执行过程不是一条线(线程)的,而是多条线(线程)共同完成的。
     3、 系统在运行的时候会为每个进程分配不同的内存区域,但是不会为线程分配内存(线程所使用的资源是它所属的进程的资源),线程组只能共享资源。那就是说,出了CPU之外(线程在运行的时候要占用CPU资源),计算机内部的软硬件资源的分配与线程无关,线程只能共享它所属进程的资源。
    4、 与进程的控制表PCB相似,线程也有自己的控制表TCB,但是TCB中所保存的线程状态比PCB表中少多了。
    5、 进程是系统所有资源分配时候的一个基本单位,拥有一个完整的虚拟空间地址,并不依赖线程而独立存在。

3. 多线程有几种实现方法,都是什么?
答:
     1.  继承Thread类
     2.  实现Runnable接口再new Thread(YourRunnableObject)
4.  多线程同步和互斥有几种实现方法?
答:
线程间的同步方法大体可分为两类:用户模式和内核模式。顾名思义,内核模式就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。
用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。内核模式下的方法有:事件,信号量,互斥量。
5. 多线程同步和互斥有何异同,在什么情况下分别使用它们?举例说明。
答:
线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。

线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。线程互斥可以看成是一种特殊的线程同步(下文统称为同步)。

6.多线程中栈与堆是共有的还是私有的?
答:
多线程中的栈是私有的,堆是共有的。

二.综合题
1.子线程循环 10 次,接着主线程循环 100 次,接着又回到子线程循环 10 次,接着再回到主线程又循环 100 次,如此循环50次,试写出代码。
答:
#include
#include
#include

unsigned int __stdcall Fun(void *pPM);
const int THREAD_NUM=1;

const int LOOP=100;
HANDLE g_hThreadEvent1;
HANDLE g_hThreadEvent2;

int main()
{
  printf("子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程循环100次,如此循环50次");
  int i=0,j;
  HANDLE hd1[THREAD_NUM];
  g_hThreadEvent1=CreateEvent(NULL,FALSE,FALSE,NULL);
  g_hThreadEvent2=CreateEvent(NULL,FALSE,TRUE,NULL);
  hd1[0]=(HANDLE)_beginthreadex(NULL,0,Fun,NULL,0,NULL);
  for(i=0;i   {
    WaitForSingleObject(g_hThreadEvent1,INIFINITE);
for(j=0;j<100;j++)
{
 printf("主线程编号是在循环第%d次,j+1");
}
SetEvent(g_hThreadEvent2);
Sleep(200);
  }
  CloseHandle(g_hThreadEvent1);
  CloseHandle(g_hThreadEvent2);
  for(i=0;i CloseHandle(hd[i]);
  return 0;
}

unsigned int __stdcall Fun(void *pPM)
{
  int num=0;
  int i=0;
  for(i=0;i   {
     WaitForSingleObject(g_hThreadEvent2,INIFINITE);
for(num=0;num<10;num++)
{
  printf("线程编号是%d,在循环第%d次\n",GetCurrentThreadId(),num+1);
}
SetEvent(g_hThreadEvent1);
  }
  return 0;
}
2.编写一个程序,开启3个线程,这3个线程的ID分别为ABC,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC.依次递推。(迅雷笔试题)
答:
#include
#include
#include

unsigned int __stdcall Fun(void *pPM);
const int THREAD_NUM=3;

const int LOOP=10;
HANDLE g_hThreadEvent[THREAD_NUM];
HANDLE hd1[THREAD_NUM];
int main()
{
  printf("三个线程,ID分别为A,B,C,并按照ABCABC...,共10遍");
  int i=0;
  for(i=0;i       g_hThreadEvent[i]=CreateEvent(NULL,FALSE,FALSE,NULL);
  for(i=0;i       hd1[i]=(HANDLE)_beginthreadex(NULL,0,Fun,(void*)i,0,NULL);
  SetEvent(g_hThreadEvent[0]);
  WaitForMultipleObjects(THREAD_NUM,hd1,TRUE,INFINITE);
  for (i = 0; i < THREAD_NUM; i++)  
  {  
     CloseHandle(hd1[i]);  
     CloseHandle(g_hThreadEvent[i]);  
  }  
  return 0;
}

unsigned int __stdcall Fun(void *pPM)
{
  int num=(int)pPM;
  int i=0;
  for(i=0;i   {
     WaitForSingleObject(g_hThreadEvent[num],INFINITE);
     printf("%c",num+'A');
if(num+1==THREAD_NUM)
       printf(" ");
SetEvent(g_hThreadEvent[(num+1)%THREAD_NUM]);
  }
  return 0;
}

3. 有四个线程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     
#include     
#include   
#include  
#include  
 
unsigned int __stdcall Fun(void *pPM);      
//线程个数  
const int THREAD_NUM = 4;  
const int FILE_NUM = 4;  
  
ofstream ofile[FILE_NUM];   
//某个线程的下一个要写的文件  
int FILE_THREAD[FILE_NUM]={0,1,2,3};  
int NEXT_LOOP[FILE_NUM]={0,1,2,3,};  
CRITICAL_SECTION g_csFile;  
//循环次数  
const int LOOP = 6;  
 
//互斥事件  
HANDLE g_hThreadEvent[THREAD_NUM];  
int main()  
{  
    printf("\t有四个线程1、2、3、4。线程1的功能就是输出1,线程2的功能就是输出2\n");  
    printf("以此类推.........现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式\n");  
  
    int i = 0 , j;  
    HANDLE hdl[THREAD_NUM];  
    InitializeCriticalSection(&g_csFile);  
    //事件开启的时候是没有触发的  
    for (i = 0; i < THREAD_NUM; i++)   
        g_hThreadEvent[i] = CreateEvent(NULL,FALSE,FALSE,NULL);  

    //将线程编号作为线程参数传进去,先转换为指针,再转换为整形,  
      
    char FILE_THREAD[] ="A.txt";  
  
    for (i = 0; i < FILE_NUM; i++)   
    {  
  
        FILE_THREAD[0] = i + 'A';  
        ofile[i].open(FILE_THREAD,ios::trunc);  
  
        if(ofile[i].fail())  
        {  
            printf("打开文件%s 失败",FILE_THREAD);  
            continue;  
        }  
    }  
    for (i = 0; i < THREAD_NUM; i++)   
        hdl[i] = (HANDLE)_beginthreadex(NULL,0,Fun,(void*)i,0,NULL);  
  
    //触发第一个线程,线程函数会按顺序自己触发下一个要执行的线程  
    SetEvent( g_hThreadEvent[0] );  
  
    WaitForMultipleObjects(THREAD_NUM,hdl,TRUE,INFINITE);  
  
    //清理  
    for (i = 0; i < THREAD_NUM; i++)  
    {  
        CloseHandle(hdl[i]);  
        CloseHandle(g_hThreadEvent[i]);  
    }  
  
    for( i  = 0 ; i< FILE_NUM;i++)  
    {  
        ofile[i].close();  
    }  
    DeleteCriticalSection(&g_csFile);  
  
    return 0;  
}  
  
unsigned int __stdcall Fun(void *pPM)  
{  
  
    int num = (int)pPM ;  
    int i = 0;  
    for( i  = 0 ; i< LOOP;i++)  
    {  
        //等待顺序触发  
        WaitForSingleObject(g_hThreadEvent[num],INFINITE);        
      
        EnterCriticalSection(&g_csFile);  
      
        printf("  线程 %d 正在向%c文件写入,下一次对文件%c操作的是线程%d\n",  
            num + 1 , FILE_THREAD[num] + 'A',FILE_THREAD[num] + 'A',(num+1)%(THREAD_NUM) +1);  
  
        ofile[FILE_THREAD[num]]<   
        Sleep(200);  
  
        //这是关键:记录下一轮对应序号要操作的文件, (num+1)%(FILE_NUM) 事件对应的线程,操作文件FILE_THREAD[num]  
        NEXT_LOOP[ (num+1)%(FILE_NUM) ] = FILE_THREAD[num] ;  
  
        if( num + 1 == FILE_NUM)  
        {  
            printf("\n");  
            //本轮写入结束,将计算好的下一轮文件操作顺序取过来  
            memcpy(&FILE_THREAD,&NEXT_LOOP,FILE_NUM *sizeof(int));  
        }  
        LeaveCriticalSection(&g_csFile);            
        //触发下一个线程,1触发2 ,2触发3,3触发4,4触发1  
        SetEvent(g_hThreadEvent[(num+1)%THREAD_NUM ]);  
    }  
    return 0;  
}  

参考博客:
1.  http://blog.csdn.net/morewindows/article/details/7392749
2.  http://blog.csdn.net/lilien1010/article/details/8119325

你可能感兴趣的:(Windows核心编程)