使用CreateThread函数创建线程

作者:Ezioooooo
来源:CSDN
原文:https://blog.csdn.net/u012877472/article/details/49721653
版权声明:本文为博主原创文章,转载请附上博文链接!


线程是进程中的一个实体,是被系统独立调度和分派的基本单位。一个进程可以拥有多个线程,但是一个线程必须有一个进程。线程自己不拥有系统资源,只有运行所必须的一些数据结构,但它可以与同属于一个进程的其它线程共享进程所拥有的全部资源,同一个进程中的多个线程可以并发执行。

在C/C++中可以通过CreateThread函数在进程中创建线程,函数的具体格式如下:

HANDLE CreateThread(
                    LPSECURITY_ATTRIBUTES lpThreadAttributes,
                    DWORD dwStackSize,
                    LPTHREAD_START_ROUTINE lpStartAddress,
                    LPVOID lpParameter,
                    DWORD dwCreationFlags,
                    LPDWORD lpThreadID
                   );

参数的含义如下:
lpThreadAttrivutes:指向SECURITY_ATTRIBUTES的指针,用于定义新线程的安全属性,一般设置成NULL;

dwStackSize:分配以字节数表示的线程堆栈的大小,默认值是0;

lpStartAddress:指向一个线程函数地址。每个线程都有自己的线程函数,线程函数是线程具体的执行代码;

lpParameter:传递给线程函数的参数;

dwCreationFlags:表示创建线程的运行状态,其中CREATE_SUSPEND表示挂起当前创建的线程,而0表示立即执行当前创建的进程;

lpThreadID:返回新创建的线程的ID编号;

如果函数调用成功,则返回新线程的句柄,调用WaitForSingleObject函数等待所创建线程的运行结束。函数的格式如下:

DWORD WaitForSingleObject(
                          HANDLE hHandle,
                          DWORD dwMilliseconds
                         );

参数的含义如下:
hHandle:指定对象或时间的句柄;

dwMilliseconds:等待时间,以毫秒为单位,当超过等待时间时,此函数返回。如果参数设置为0,则该函数立即返回;如果设置成INFINITE,则该函数直到有信号才返回。

一般情况下需要创建多个线程来提高程序的执行效率,但是多个线程同时运行的时候可能调用线程函数,在多个线程同时对一个内存地址进行写入操作,由于CPU时间调度的问题,写入的数据会被多次覆盖,所以要使线程同步。

就是说,当有一个线程对文件进行操作时,其它线程只能等待。可以通过临界区对象实现线程同步。临界区对象是定义在数据段中的一个CRITICAL_SECTION结构,Windows内部使用这个结构记录一些信息,确保同一时间只有一个线程访问改数据段中的数据。

使用临界区的步骤如下:

(1)初始化一个CRITICAL_SECTION结构;在使用临界区对象之前,需要定义全局CRITICAL_SECTION变量,在调用CreateThread函数前调用InitializeCriticalSection函数初始化临界区对象;

(2)申请进入一个临界区;在线程函数中要对保护的数据进行操作前,可以通过调用EnterCriticalSection函数申请进入临界区。由于同一时间内只能有一个线程进入临界区,所以在申请的时候如果有一个线程已经进入临界区,则该函数就会一直等到那个线程执行完临界区代码;

(3)离开临界区;当执行完临界区代码后,需要调用LeaveCriticalSection函数离开临界区;

(4)删除临界区;当不需要临界区时调用DeleteCriticalSection函数将临界区对象删除;

下面的代码创建了5个线程,每个线程在文件中写入10000个“hello”:

#include <stdio.h>
#include <windows.h>
HANDLE hFile;
CRITICAL_SECTION cs;//定义临界区全局变量
//线程函数:在文件中写入10000个hello
DWORD WINAPI Thread(LPVOID lpParam)
{
    int n = (int)lpParam;
    DWORD dwWrite;
    for (int i = 0;i < 10000;i++)
    {
        //进入临界区
        EnterCriticalSection(&cs);
        char data[512] = "hello\r\n";
        //写文件
        WriteFile(hFile, data, strlen(data), &dwWrite, NULL);
        //离开临界区
        LeaveCriticalSection(&cs);
    }
    printf("Thread #%d returned successfully\n", n);
    return 0;
}
int main()
{
    char *filename = "hack.txt";
    WCHAR name[20] = { 0 };
    MultiByteToWideChar(CP_ACP, 0, filename, strlen(filename) + 1, name, sizeof(name) / sizeof(name[0]));
    //创建文件
    hFile = CreateFile(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        printf("CreateFile error.\n");
        return 0;
    }
    DWORD ThreadID;
    HANDLE hThread[5];
    //初始化临界区
    InitializeCriticalSection(&cs);
    for (int i = 0;i < 5;i++)
    {
        //创建线程,并调用Thread写文件
        hThread[i] = CreateThread(NULL, 0, Thread, (LPVOID)(i + 1), 0, &ThreadID);
        printf("Thread #%d has been created successfully.\n", i + 1);
    }
    //等待所有进程结束
    WaitForMultipleObjects(5, hThread, TRUE, INFINITE);
    //删除临界区
    DeleteCriticalSection(&cs);
    //关闭文件句柄
    CloseHandle(hFile);
    return 0;
}

结果如图:
在这里插入图片描述


以上为原文,对代码示例做了些许改动:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
HANDLE hFile;
CRITICAL_SECTION cs;//定义临界区全局变量
//线程函数:在文件中写入10000个hello
DWORD WINAPI Thread(LPVOID lpParam)
{
	int n = (int)lpParam;
	DWORD dwWrite;
	for (int i = 0; i < 10000; i++)
	{
		//进入临界区
		EnterCriticalSection(&cs);
		char data[512] = "hello\r\n";
		//写文件
		WriteFile(hFile, data, strlen(data), &dwWrite, NULL);
		//离开临界区
		LeaveCriticalSection(&cs);
	}
	printf("Thread #%d returned successfully\n", n);
	return 0;
}
int main()
{
	char filename[10] = "hack.txt";
	WCHAR name[20] = { 0 };
	MultiByteToWideChar(CP_ACP, 0, filename, strlen(filename) + 1, name, sizeof(name) / sizeof(name[0]));
	//创建文件
	hFile = CreateFile((LPCSTR)name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		printf("CreateFile error.\n");
		return 0;
	}
	DWORD ThreadID;
	HANDLE hThread[5];
	//初始化临界区
	InitializeCriticalSection(&cs);
	for (int i = 0; i < 5; i++)
	{
		//创建线程,并调用Thread写文件
		hThread[i] = CreateThread(NULL, 0, Thread, (LPVOID)(i + 1), 0, &ThreadID);
		printf("Thread #%d has been created successfully.\n", i + 1);
	}
	//等待所有进程结束
	WaitForMultipleObjects(5, hThread, TRUE, INFINITE);
	//删除临界区
	DeleteCriticalSection(&cs);
	//关闭文件句柄
	CloseHandle(hFile);
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Pro2015/article/details/88718874