线程控制

Posted shiningarmor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程控制相关的知识,希望对你有一定的参考价值。

1.线程控制
控制线程状态的API函数:
//挂起线程:                
::SuspendThread(hThread);                
                
//恢复线程:                
::ResumeThread(hThread);                
                
//终止线程:                
    //方式一:                
    ::ExitThread(DWORD dwExitCode);  
        //参数中没有线程句柄,在线程函数中使用;
        //参数dwExitCode为线程退出码,将作为线程处理函数的返回值,用来描述线程的非正常退出
        //每一个线程都有自己的堆栈,该函数终止的线程会清理堆栈;
        //该函数一旦调用,线程将不能再被操作,但该函数并不会释放堆中的内存,因此存在内存溢出的隐患;  
       
    //方式二:线程函数返回   
       //线程函数执行完后会结束线程,因为是正常结束,可以自己写代码来释放堆中申请的内存;              
                
    //方式三:                
    ::TerminateThread(hThread,2);    //第二个参数为线程退出码                
    ::WaitForSingleObject(hThread,INFINITE); 
        //TerminateThread并不会清理堆栈,这样的好处是其它地方用堆栈中的变量时不会出问题;     
           
//判断线程是否结束                
BOOL GetExitCodeThread(                
  HANDLE hThread,                
  LPDWORD lpExitCode                
);                
    //STILL_ACTIVE //正在运行                
    //参数:                                
        //hThread: 要结束的线程句柄                                
        //dwExitCode: 指定线程的退出代码。可以通过GetExitCodeThread来查看一个线程的退出代码         
ExitThread和TerminateThread的区别:
    都是用来结束线程的,ExitThread是同步的,也就是ExitThread执行完后程序才能继续往下执行;
    TerminateThread是异步调用;也就是单独起了一个线程来让目标线程结束; 
    TerminateThread调用后不能保证立即结束线程,在后面写线程结束后要执行的代码可能有问题;
    解决办法是用 WaitForSingleObject,该函数会阻塞线程直到TerminateThread的目标线程真正结束;
 
线程挂起后恢复时并不会立即运行;
因为windows并不是实时的操作系统,只有在调度程序给可调度状态的线程分配cpu时间时才会运行;
因此windows中无法实现在某个确定的时间点运行一个线程;
 
2.线程contex结构
每个线程在执行的时候,都会独自占用一个CPU,
当系统中的线程数量 > CPU的数量时,就会存在多个线程共用一个CPU的情况。
但CPU每次只能运行一个线程,Windows每隔20毫秒会进行线程的切换,
那比如线程A执行到地址:0x2345678 eax:1 ecx:2 edx:3 ebx:4...还有eflag标志寄存器中的值等等。。。             
此时,线程执行时间到了,被切换到了线程B。。。。
当线程B的时间片也到了,再切换回线程A时,系统是如何知道该从哪个地址开始执行呢?被切换前用到的各种寄存器的值该如何恢复呢?
 
context结构:该结构包含了特定cpu的寄存器数据
typedef struct _CONTEXT {                            
                            
    //                            
    // The flags values within this flag control the contents of                            
    // a CONTEXT record.                            
    //                            
    // If the context record is used as an input parameter, then                            
    // for each portion of the context record controlled by a flag                            
    // whose value is set, it is assumed that that portion of the                            
    // context record contains valid context. If the context record                            
    // is being used to modify a threads context, then only that                            
    // portion of the threads context will be modified.                            
    //                            
    // If the context record is used as an IN OUT parameter to capture                            
    // the context of a thread, then only those portions of the thread‘s                            
    // context corresponding to set flags will be returned.                            
    //                            
    // The context record is never used as an OUT only parameter.                            
    //                            
                            
    DWORD ContextFlags;                            
                            
    //                            
    // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is                            
    // set in ContextFlags.  Note that CONTEXT_DEBUG_REGISTERS is NOT                            
    // included in CONTEXT_FULL.                            
    //                            
                            
    DWORD   Dr0;                            
    DWORD   Dr1;                            
    DWORD   Dr2;                            
    DWORD   Dr3;                            
    DWORD   Dr6;                            
    DWORD   Dr7;                            
                            
    //                            
    // This section is specified/returned if the                            
    // ContextFlags word contians the flag CONTEXT_FLOATING_POINT.                            
    //                            
                            
    FLOATING_SAVE_AREA FloatSave;                            
                            
    //                            
    // This section is specified/returned if the                            
    // ContextFlags word contians the flag CONTEXT_SEGMENTS.                            
    //                            
                            
    DWORD   SegGs;                            
    DWORD   SegFs;                            
    DWORD   SegEs;                            
    DWORD   SegDs;                            
                            
    //                            
    // This section is specified/returned if the                            
    // ContextFlags word contians the flag CONTEXT_INTEGER.                            
    //                            
                            
    DWORD   Edi;                            
    DWORD   Esi;                            
    DWORD   Ebx;                            
    DWORD   Edx;                            
    DWORD   Ecx;                            
    DWORD   Eax;                            
                            
    //                            
    // This section is specified/returned if the                            
    // ContextFlags word contians the flag CONTEXT_CONTROL.                            
    //                            
                            
    DWORD   Ebp;                            
    DWORD   Eip;                            
    DWORD   SegCs;              // MUST BE SANITIZED                            
    DWORD   EFlags;             // MUST BE SANITIZED                            
    DWORD   Esp;                            
    DWORD   SegSs;                            
                            
    //                            
    // This section is specified/returned if the ContextFlags word                            
    // contains the flag CONTEXT_EXTENDED_REGISTERS.                            
    // The format and contexts are processor specific                            
    //                            
                            
    BYTE    ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];                            
                            
} CONTEXT;                            
                            
 
进程就是程序的4GB空间,线程就是EIP;
当一个线程切换时,为了再次执行时能接着执行,会将寄存器的信息保存context结构中;
 
如何获取context结构中的值:
例如:获取context中的eip
//挂起线程;不挂起获取的值不准确                    
SuspendThread(线程句柄);                    
                    
CONTEXT context;                        
                    
//设置要获取的类型                    
context.ContextFlags = CONTEXT_CONTROL;                    
                    
//获取                    
BOOL ok = ::GetThreadContext(hThread,&context);                    
                    
//设置                    
context.Eip = 0x401000;     
               
SetThreadContext(hThread,&context);         

 

         

以上是关于线程控制的主要内容,如果未能解决你的问题,请参考以下文章

多个用户访问同一段代码

MySQL系列:kafka停止命令

硬核!管理mysql数据库的工具

java开发的项目案例,大厂内部资料

Java进阶之光!2021必看-Java高级面试题总结

Java工程师面试题,二级java刷题软件