一、线程

  与前面介绍的进程一样,线程也有两部分组成:

  1)一个线程内核对象,操作系统用它来管理线程。内核对象中还存储了线程的各种统计信息,包括挂起计数、退出代码等,以便于系统对线程的管理。内核对象中有一个CONTEXT结构,这个结构中存储了线程上一次执行的时候CPU寄存器的状态。

  2)一个线程栈,用于维护线程执行时所需的所有函数参量和局部变量。

  位于同一个进程的线程共享进程的地址空间且它们共享进程句柄表。因为句柄表是针对进程的。进程需要很多的系统资源,而线程仅仅需要一个线程内核对象和线程栈可以了,因此线程比进程的开销要小得多。采用多线程来处理问题也是理所当然的了。

  采用多线程可以提高程序的执行效率,但是多线程也存在很多问题。在尝试使用多线程时如果处理不当还可能会引入新的问题。如同步问题。

  二、编写第一个线程函数

  每个线程都需要一个入口点函数。这是线程执行的起点。主线程的入口点函数是_tmain或_tWinmain。如果在进程中创建新线程必须提供自己的入口点函数。

  形如:


DWORD WINAPI ThreadFunc(PVOID pvParam){
    DWORD dwResult = 0;
     ...
    return(dwResult);
}


  线程函数可以是任何我们希望它执行的任务,终线程函数会终止并返回。类似于进程内核对象,如果线程内核对象使用计数变为0,则会被销毁。

  1)默认情况下主线程的入口点函数必须命名为main,wmain,WinMain或wWinMain。我们可以通过设置/ENTRY:链接器选项来指定另一个函数作为入口点函数。

  2)主线程入口点函数有字符串参数,所以它提供了ANSI/Unicode版本。相反,线程函数只有一个参数,其意义可由我们定义。可以为其传递一个值,也可以将其作为某个数据结构的指针。这需要在线程函数内部做类型转换。

  3)线程函数必须返回一个值,它的值传递给ExitThread,作为线程的退出代码。

  4)线程函数尽可能地使用局部变量或函数参数,它们是在线程栈上创建的。不太可能被其他线程破坏。使用静态变量或全局变量时其他线程可以访问这些变量,这会导致同步和互斥问题。

  三、CreateThread 函数

  如果想创建一个或多个辅助线程,只需让一个正在运行的线程调用CreateThread :

  HANDLE CreateThread(
  PSECURITY_ATTRIBUTES   psa,                      //指向SECURITY_ATTRIBUTES结构的指针;
  DWORD   cbStackSize,                                      //制定线程可以为其线程栈使用多少地址空间; 栈空间大小 ,传入0则默认使用内部值 链接器/STACK 可以改变大小  默认1M
  PTHREAD_START_ROUTINE  pfnStartAddr, //线程函数的地址;
  PVOID pvParam,                                                  //线程函数参数
  DWORD dwCreateFlags,                                   //指定额外的标志来控制线程的创建;   CREATE_SUSPENDED 暂停执行
  PDWORD pdwThreadID);                                 //存储系统分配给新线程的ID;

  例:


DWORD  WINAPI  FirstThread(PVOID  pvParam)
       {
           int x=0;  //这里的函数,为SecoundThread 的返回值,好声明为static,防止FirstThread 执行完,SecoundThread 返回时,访问栈越界。
           DWORD   dwThreadID;
           HANDLE  hThread = CreatThread( NULL, 0 , SecondThread , (PVOID)&x , 0, &dwThread);
        }
     
   DWORD  WINAPI  SecondThread (PVOID  pvParam)
       {
              *(int *)pvParam =5;
       }


  调用 CreateThread 时,系统会创建一个线程内核对象。系统从进程地址空间中分配内存给线程栈使用。新线程可以访问进程内核对象的所有句柄、进程中的所有内存以及同一个进程中其它所有线程的栈。

  CreateThread 函数时用于创建线程的Windows函数。不过如果写的是C/C++代码,不要调用 CreateThread。 正确地选择是使用Microsoft C++运行库函数_beginthreadex。如果使用的不是Microsoft C++编译器,你的编译器的提供商应该提供类似的函数来替代 CreateThread 。不管这个替代函数时什么,都必须使用它。