一、线程的基本概念
线程的英文单词是 thread
,翻译成对应的中文有
“
分支
”
、
“
枝干
”
的意思,
当然这里翻译成
“
线程
”
属于意译了。提高线程就不得不提与线程相关联的
另外一个概念
“
进程
”
,一个
“
进程
”
代表计算机中实际跑起来的一个程序,
在现代操作系统的保护模式下,每个进程拥有自己独立的进程地址空间
和上下文堆栈。但是就一个程序本身执行的操作来说,进程其实什么也
不做(不执行任何进程代码),它只是提供一个大环境容器,在进程中
实际的执行体是
“
线程
”
。
wiki
百科上给线程的定义是:
In computer science, a thread of execution is the smallest sequence of
programmed instructions that can be managed independently by ascheduler, which is typically a part of the operating system.计算机科学中,线程是操作系统管理的、可以执行编制好的最小单位的
指令序列的调度器。
翻译的有点拗口,通俗地来说,线程是进程中实际执行代码的最小单
元,它由操作系统安排调度(何时启动、何时运行和暂停以及何时消
亡)。
二、关于线程的常见问题
(1)一个进程至少有一个线程
上面也提到了,线程是进程中实际干活的单位,因此一个进程至少得有
一个线程,我们把这个线程称之为
“
主线程
”
,也就是说,
一个进程至少要
有一个主线程
。
(2)主线程退出,支线程也将退出吗?
在 Windows 系统中,当一个进程存在多个线程时,如果主线程执行结束
了,那么这个时候即使支线程(也可以叫
工作线程
)还没完成相关的代
码执行,支线程也会退出,也就是说,主线程一旦退出整个进程也就结
束了。之所以强调这一点是,很多多线程编程的初学者经常犯在工作线
程写了很多逻辑代码,但是没有注意到主线程已经提前退出,导致这些工作线程的代码来不及执行。解决这一问题的方案很多,核心就是让主
线程不要退出,或者至少在工作线程完成工作之前主线程不要退出。常
见的解决方案有主线程启动一个循环或者主线程等待工作线程退出后再退出。
(3)某个线程崩溃,会导致进程退出吗?
一般来说,每个线程都是独立执行的单位,每个线程都有自己的上下文堆栈,一个线程的崩溃不会对其他线程造成影响。但是通常情况下,一
个线程崩溃会产生一个进程内的错误,例如,在
Linux
操作系统中,可
能会产生一个
Segment Fault
错误,这个错误会产生一个信号,操作系统
默认对这个信号的处理就是结束进程,整个进程都被销毁了,这样的话
这个进程中存在的其他线程自然也就不存在了。
三、线程的创建
Windows 上创建线程使用 CreateThread,其函数签名如下:
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
参数 lpThreadAttributes,是线程的安全属性,一般设置为 NULL。 参数 dwStackSize,线程的栈空间大小,单位为字节数,一般指定 为 0,表示使用默认大小。 参数 lpStartAddress,为线程函数,其类型 是 LPTHREAD_START_ROUTINE,这是一个函数指针类型,其定义如下:
typedef DWORD ( __stdcall *LPTHREAD_START_ROUTINE )(LPVOID lpThreadParameter);
四、实践(创建线程)
#include <Windows.h>
#include <stdio.h>
DWORD WINAPI ThreadProc(LPVOID lpParameters)
{
while (true)
{
//睡眠 1 秒,Windows 上的 Sleep 函数参数事件单位为毫秒
Sleep(1000);
printf("I am New Thread!\n");
}
}
int main()
{
DWORD dwThreadID;
HANDLE hThread = CreateThread(NULL, 0, ThreadProc,
NULL, 0, &dwThreadID);
if (hThread == NULL)
{
printf("Failed to CreateThread.\n");
}
while (true)
{
Sleep(1000);
//权宜之计,让主线程不要提前退出
}
return 0;
}