Windows线程面试题附带答案(自己整理)

联系QQ:1024275440
1.创建进程的函数是什么:
2.创建线程的函数是什么:
3.如何让被创建线程挂起状态:
4.如何让创建的线程立刻运行:
5.线程上下文作用是什么:
6.如何打开一个现有的线程对象:
7.请写出返回当前进程句柄的函数:
8.请写出返回当前线程句柄的函数:
9.Usage Count的作用是什么:
10.等待线程结束函数:
11.唤醒挂起线程的函数:
12.Suspend Count暂停次数有什么作用:
13.如何挂起一个线程:
14.上下文转换的作用是什么:
15.GetExitCodeThread()函数的作用是什么:
16.Signaled是否受信作用是什么:
17.CONTEXT结构保存了什么信息:
18.GetExitCodeThread()函数的作用是什么:
19.ExitThread()函数的作用是什么:
20.TerminateThread()函数和ExitProcess()函数作用是什么:
21.请写出windows支持的6个优先类:
22.线程优先级最大值是多少,应该使用哪个函数修改线程优先级:
23.进程是否可以修改优先级:
24.等待直到线程进入受信状态的函数是哪个:
25.临界区对象的作用是什么,请写出临界区数据段结构名、初始化函数、关键代码段函数、释放关键代码段函数、释放临界区结构函数。
26.互锁函数是什么条有什么作用:
27.创建事件内核对象的函数是什么:
28.事件内核对象的作用是什么,在什么环境下
29.线程局部存储(TLS)作用是什么:
答案在下面:
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
1.CreateProcess
2.CreateThread
3.CreateThread函数dwCreationFlags参数设置为CREATE_SUSPENDED
4.CreateThread函数dwCreationFlags参数设置为0
5.CONTEXT线程上线文:每个线程都有自己的一组CPU寄存器,被称为线程上线文,这组寄存器值保存在一个CONTEXT结构里,反映了该线程上次运行时CPU的状态
6.OpenThread函数
7.GetCurrentProcess()函数
8.GetCurrentThread();函数
9.Usage Count成员是记录了线程内核对象的使用次数,当Usage Count值为0则说明没有任何进程引用此内核对象,于是线程内核对象从内存中撤销,当时用CreateThread或者是OpenThread等会使Usage Count值加一。
10.WaitForSingleObject();
11.ResumeThread();
12.Suspend Count暂停次数是用于指明线程的暂停次数,当调用CreateProcess创建主线程或CreateThread函数时,线程内核对象被创建,其暂停计数被初始化1则是暂停状态,这会阻止新创建的线程被调度到CPU中,因为线程初始化需要时间,当完全初始化之后,CreateProcess或CreateThread检查是否传递了CREATE_SUPENDED标志,如果传递则返回同时新的线程处于暂停状态,可以在线程机会执行任意代码之前改变线程的运行环境(线程上下文)达到目的后可以使用ResumeThread函数唤醒一个挂起的线程。
13.SuspendThread()挂起一个线程
14.将CONTEXT上下文装入CPU寄存器,这一过程被称为线程上下文
15.获得线程退出码
16.Signaled是否受信是指线程对象Signaled的值是否为FALSE,FASEL即未受信当程序运行期间,Signaled的值永远是FALSE(未受信),线程运行结束之后系统将Signaled设置为TRUE即此对象等待函数返回(类似于WaitForSingleObject函数)
线程运行阶段没有处于受信状态,线程结束处于受信状态
17.线程上下文信息(既包括寄存器值、使用次数、暂停次数等)
18.GetExitCodeThread函数返回线程的退出码,如果线程还在运行则返回STILL_ACTIVE如果线程结束了则返回退出码
19.ExitThread()函数中止当前线程比如exitThread(0);会使当前线程中止函数形参是线程退出码
20.TerminateThread()函数可以在一个线程中强制中止另一个线程,需要注意的是如果是强制中止线程那么系统不会释放线程时使用的堆栈,ExitProcess()函数是类似于对每一个线程使用TerminateThread()函数
21.windows支持的优先级类有6中idle/below/normal/above normal/high/real-time
22.0~31线程优先级号码0是最低31是最高,系统分配CPU时如果有31优先级优先运行,SetThreadPriority();函数可以修改线程优先级
23.进程可以修改优先级但是在编程中很少使用。
24.WaitForMultipleObject函数用于等待多个内核对象,前两个参数分别为要等待的内核对象的个数和句柄指针,第三个参数为TRUE则说明要等待内核对象完全变成受信状态后函数才可以返回。
25.例子:
#include"CreateThreadDemo.h"
static unsigned int g_nInt1=NULL;
static unsigned int g_nInt2 = NULL;
BOOL g_cbool = TRUE;
CRITICAL_SECTION g_cs;//声明临界区对象
#define 初始化临界区对象 InitializeCriticalSection(&g_cs);
#define 关键代码段 EnterCriticalSection(&g_cs);
#define 释放关键代码段 LeaveCriticalSection(&g_cs);
#define 释放临界区对象 DeleteCriticalSection(&g_cs);
DWORD WINAPI Thread1(LPVOID lpParam) {
while (g_cbool) {
关键代码段
g_nInt1++;
g_nInt2++;
释放关键代码段
}
return NULL;
}
int main() {
初始化临界区对象
HANDLE handle[2];
DWORD dwid;
handle[0] = CreateThread(0,0,Thread1,0,CREATE_SUSPENDED,&dwid);
handle[1] = CreateThread(0,0,Thread1,0,CREATE_SUSPENDED,&dwid);
SetThreadPriority(handle[0], THREAD_PRIORITY_TIME_CRITICAL);
SetThreadPriority(handle[1], THREAD_PRIORITY_ABOVE_NORMAL);
ResumeThread(handle[0]);
ResumeThread(handle[1]);
Sleep(1000);
g_cbool = FALSE;
WaitForSingleObject(handle, INFINITE);
CloseHandle(handle[0]);
CloseHandle(handle[1]);
释放临界区对象
cout << g_nInt1 << endl;
cout << g_nInt2 << endl;
}
26.简单来说互锁函数会传入一个指针作为形参,可以递增或者递减变量,不同的线程也可以使用此机制,互锁函数可以阻止其他线程的同时使用此变量。
InterlockedIncrement(LONG volatile* Addend)递增互锁函数,形参是指向要递增的变量。
InterlockedDecrement(LONG volatile* Addend);递减互锁函数,形参是指向要递减的变量
互锁函数主要用于变量操作,操作该变量时其他线程无法对共享的变量操作。
27.
CreateEvent()创建事件内核对象
OpenEvent()打开事件内核对象
SetEvent将事件状态设置受信
ResetEvent将事件状态设置未受信
28.
事件内核对象类似于临界区对象和互锁函数但是提供了更多样化的操作,事件内核对象可以与其他线程之间进行通信可以用于某一个线程完成初始化或者其他操作之后通知其他线程可以进行操作,事件内核对象有两种模式一种是自动重置和手动重置,自动重置对象会在线程函数执行之后将事件内核对象设置为受信状态(即线程结束),那么其他线程便可以执行,如果将事件内核对象设置为手动重置则函数返回仍然是未受信状态(即线程仍在运行),其他线程无法获得执行,需要使用SetEvent函数设置为受信状态.
例子:
//事件内核对象例子(自动重置)
#include
#include
using namespace std;
unsigned int uInt=NULL;
unsigned int uIntTwo = NULL;
bool EventBool = true;
DWORD WINAPI EventFunction(LPVOID lpData) {
HANDLE handle=OpenEvent(EVENT_ALL_ACCESS,FALSE, (LPCWSTR)“EventDemo”);
WaitForSingleObject(handle,INFINITE);
while (EventBool) {
uInt++;
uIntTwo++;
}
CloseHandle(handle);
return NULL;
}
int main() {
HANDLE handleEvent=CreateEvent(NULL, false,true,(LPCWSTR)“EventDemo”);//创建事件内核
DWORD dwThreadId[2];
HANDLE handle[2];
handle[0]=CreateThread(0,0,EventFunction,0,CREATE_SUSPENDED,&dwThreadId[0]);
handle[1] = CreateThread(0, 0, EventFunction, 0, CREATE_SUSPENDED, &dwThreadId[1]);
ResumeThread(handle[0]);
ResumeThread(handle[1]);
Sleep(1000);
EventBool = false;
cout << “uINT:” << uInt << endl;
cout << “uIntTwo:” << uIntTwo << endl;
CloseHandle(handleEvent);
CloseHandle(handle[0]);
CloseHandle(handle[1]);
}

29.线程局部存储(TLS)的作用主要是存储线程的局部变量就像名字一样,所需函数如下:
TlsAlloc()返回一个TLS索引
系统为每一个进程都维护了位数组,位数组的默认值FREE当使用TlsAlloc函数时改为INCUSE返回的值就是数组的下标(索引),这个数组唯一的用途就是记忆哪一个下标在使用中,该函数的主要目的是确保TLS索引不重复
DWORD t1=TlsAlloc();第一个为0x1
DWORD t2=TlsAlloc();第二个为0x2
这样可以确保TlsSetValue函数的索引是不重复的
TlsSetValue()函数
主要用于存储TLS索引与对应要设置的值类似于map集合索引就是key
TlsGetValue()函数
主要是通过TLS索引获取对应的索引值
TlsFree()释放存储索引,即使TlsAlloc维护的位数组重置
线程局部索引每个线程自己独有的不是共享的所以叫做线程局部存储
#include
#include
#include
using namespace std;
DWORD g_tls = 0x0;
HANDLE handle[10];
mapmapTls;
DWORD WINAPI TlsFunction(LPVOID lpdata) {
DWORD dwStart = GetTickCount();//获取当前时间
TlsSetValue(g_tls,&dwStart);//设置索引
int i = 0;
while (i <= 10000) {
i++;
}
DWORD dwElapsed = GetTickCount();
dwElapsed = dwElapsed - (DWORD)TlsGetValue(g_tls);//获取索引
mapTls.insert(make_pair(static_cast(lpdata), dwElapsed));
return dwElapsed;
}

int main() {
g_tls = TlsAlloc();//返回一个TLS索引
for (int i = 0; i <10;i++) {
handle[i] = CreateThread(0,0,TlsFunction,(LPVOID)i,0,0);
}
for (int i = 0; i < 10;i++) {
WaitForSingleObject(handle[i],INFINITE);
CloseHandle(handle[i]);
}
TlsFree(g_tls);//释放线程局部索引
for (auto Element = mapTls.begin(); Element != mapTls.end();Element++) {
cout << “id:” << Element->first<<“运行时间:” }
}

你可能感兴趣的:(c++,多线程,c++,面试)