C语言多线程基础-01-线程的创建与销毁

一.线程创建

首先要关联头文件Window.h,需要使用Windows系统的底层方法

1.1 线程创建演示:

//定义一个方法,弹出一个消息框
//该方法返回值为DWORD WINAPI类型,参数为一个空指针
DWORD WINAPI run(void * p) {
    MessageBox(0, "多线程测试", "信息", 0);
}
//main方法中开启线程
int main(void) {
    //使用_beginthread方法开启线程,让开启的线程执行run方法
    _beginthread(run, 0, NULL);
    //使用CreateThread方法开启线程,让开启的线程执行run方法
    CreateThread(NULL, 0, run, NULL, 0, NULL);  
    system("pause");
    return 0;
}

执行程序,结果如下,同时弹出两个消息框(不使用多线程时必须关闭一个消息框才会弹出下一个)
_beginthread方法和CreateThread各开启了一个线程,两个线程均弹出了一个消息框

C语言多线程基础-01-线程的创建与销毁_第1张图片

1.2 线程创建方法详解:

1)_beginthread方法

_beginthread方法的定义

uintptr_t _beginthread( // NATIVE CODE  
   void( __cdecl *start_address )( void * ),  
   unsigned stack_size,  
   void *arglist   
);  

_beginthread方法的参数

参数 含义
start_address 启动开始执行新线程的例程的地址,是一个指针类型的数据,可以使用函数名做为参数,因为函数名就是一个指针
stack_size 用于设置新开启的线程的线程栈的大小(每个线程都有一个私有的线程栈),如果设置为0,则会按照默认大小创建
arglist 要传递到新线程的参数列表或 NUL

2)CreateThread方法

CreateThread方法的定义

HANDLE WINAPI CreateThread(
  _In_opt_  LPSECURITY_ATTRIBUTES  lpThreadAttributes,
  _In_      SIZE_T                 dwStackSize,
  _In_      LPTHREAD_START_ROUTINE lpStartAddress,
  _In_opt_  LPVOID                 lpParameter,
  _In_      DWORD                  dwCreationFlags,
  _Out_opt_ LPDWORD                lpThreadId
);

CreateThread方法的参数

参数 含义
lpThreadAttributes 用于设置线程安全级别
dwStackSize 用于设置新开启的线程的线程栈的大小(每个线程都有一个私有的线程栈),如果设置为0,则会按照默认大小创建
lpStartAddress 启动开始执行新线程的例程的地址,是一个指针类型的数据,可以使用函数名做为参数,因为函数名就是一个指针
dwCreationFlags 指注册表的键值,设置为0即可,程序执行时编译器会根据系统自动查找注册表的键值
lpThreadId 线程ID

3)创建线程涉及到的方法的返回值

run方法的返回值

创建线程的两个方法中,均有一个参数用来指定新开启的线程要执行的方法,该方法返回一个DWORD WINAPI类型的返回值,根据DWORD WINAPI的定义,可以看出是一个long类型的数据

typedef unsigned long       DWORD;
#define APIENTRY    WINAPI

DWORD

DWORD全称Double Word,是指注册表的键值,每个word为2个字节的长度,DWORD双字即为4个字节
设备驱动程序和服务的许多参数都是DWORD类型,以二进制、十六进制或十进制格式显示在注册表编辑器中
DWORD根据操作系统的不同,被定义成了不同的长度,比如vs8(xp)中,DWORD被定义成了如下的类型:typedef unsigned long DWORD; 而unsigned long 的长度则是4个字节即32位,如果是在64位的操作系统中,这个长度可能会更长,取决于当前操作系统以及开发环境

CreateThread方法,和_beginthread方法的返回值:

一个HANDLE类型的数据

HANDLE

上述两个创建线程的方法都返回一个HANDLE WINAPI类型的参数,HANDLE 的中文含义是把手,操纵,专业术语为句柄。

HANDLE详解

HANDLE是Windows操作系统中的一个概念。在Windows程序中,有各种各样的资源(窗口、图标、光标等),系统在创建这些资源时会为它们分配内存,并返回标示这些资源的标示号,即句柄。

句柄:

指的是一个核心对象在某一个进程中的唯一索引,而不是指针。由于地址空间的限制,句柄所标识的内容对进程是不可见的,只能由操作系统通过进程句柄列表来进行维护。

句柄列表:

每个进程都要创建一个句柄列表,这些句柄指向各种系统资源,比如信号量,线程,和文件等,进程中的所有线程都可以访问这些资源。

二.线程销毁

2.1 线程销毁演示:

void main() {

    printf("测试第一种线程结束方法");
    system("pause");
    //_beginthread(endThread_1,0, NULL);

    printf("测试第二种线程结束方法");
    system("pause");
    //CreateThread(NULL, 0, endThread_2, NULL, 0, NULL);

    printf("测试第三种线程结束方法");
    system("pause");
    HANDLE handle = CreateThread(NULL, 0, endThread_3, NULL, 0, NULL);
    Sleep(3000);
    //外部退出线程的方法,参数为需要被结束的线程的HANDLE值
    TerminateThread(handle , 0 );
    system("pause");
}
DWORD WINAPI endThread_1(void *p) {
    int i = 1;
    while (1) {
        printf("\n%d\n", i);
        Sleep(1000);
        i++;
        if (i == 10) {
            //内部退出线程的方法,线程执行到该语句后结束
            _endthread();
        }
    }
}
DWORD WINAPI endThread_2(void *p) {
    int i = 1;
    while (1) {
        printf("\n%d\n", i);
        Sleep(1000);
        i++;
        if (i == 10) {
            //内部退出线程的方法,线程执行到该语句后结束
            ExitThread(0);
        }
    }
}
DWORD WINAPI endThread_3(void *p) {
    int i = 1;
    while (1) {
        printf("\n%d\n", i);
        Sleep(1000);
        i++;
    }
}

上述程序的执行情况:

前两种线程结束方法,在开始执行后打印数字,当打印到数字10时停止,线程结束。第三种方法在开始执行后打印数字,打印到数字3时停止打印

2.2 线程销毁方法详解:

1)_endthread方法

_endthread方法的定义

void _endthread( void );

2)ExitThread方法

ExitThread方法的定义

VOID WINAPI ExitThread(
  _In_ DWORD dwExitCode
);

dwExitCode参数是,线程的退出代码,输入0即可

3)TerminateThread方法

TerminateThread方法的定义

BOOL WINAPI TerminateThread(
  _Inout_ HANDLE hThread,
  _In_    DWORD  dwExitCode
);

hThread参数是线程的HANDLE值
dwExitCode参数是,线程的退出代码,输入0即可

你可能感兴趣的:(C/C++多线程)