GHOST系统之家 - Windows系统光盘下载网站!
当前位置:GHOST系统之家>电脑问题 > 网络安全编程:多线程编程基础知识

网络安全编程:多线程编程基础知识

来源:Ghost系统之家浏览:时间:2023-02-18 09:06:47

线程是进程中的一个执行单位(每个进程都必须有一个主线程),一个进程可以有多个线程,而一个线程只存在于一个进程中。在数据关系上,进程与线程是一对多的关系。线程不拥有系统资源,线程所使用的资源全部由进程向系统申请,线程拥有的是CPU的时间片。

在单处理器上(或单核处理器上),同一个进程中的不同线程交替得到CPU的时间片。在多处理器上(或多核处理器上),不同的线程可以同时运行在不同的CPU上,这样可以提高程序运行的效率。除此之外,在有些方面必须使用多线程。比如,如果在扫描磁盘并同时在程序界面上同步显示当前扫描的位置时,必须使用多线程。因为在程序界面上显示和磁盘的扫描工作在同一个线程中,而且界面也在不停进行重新显示,这样就会导致软件看起来像是卡死一样。在这种情况下,分为两个线程就可以解决该问题,界面的显示由主线程完成,而扫描磁盘的工作由另外一个线程完成,两个线程协同工作,这样就可以达到实时显示当前扫描状态的效果了。

首先了解一下线程的创建。线程的创建使用CreateThread()函数,该函数的原型如下:

参数说明如下。

lpThreadAttributes: 指明创建线程的安全属性,为指向 SECURITY_ATTRIBUTES 结构的指针,该参数一般设置为NULL。

dwStackSize: 指定线程使用缺省的堆栈大小,如果为 NULL,则与进程主线程栈相同。

lpStartAddress:指定线程函数,线程即从该函数的入口处开始运行,函数返回时就意味着线程终止运行,该函数属于一个回调函数。线程函数的定义形式如下:

线程函数的返回值为DWORD类型,线程函数只有一个参数,该参数在CreateThread()函数中给出。该函数的函数名称可以任意给定。很多时候并不能保证执行了CreateThread()函数后线程就会立即启动,线程的启动需要等待CPU的调度,CPU将时间片给该线程时,该线程才会执行,当然这个时间短到可以忽略它。

lpParameter:该参数表示传递给线程函数的一个参数,可以是指向任意数据类型的指针。这里是一个指针,可以方便的将多个参数通过结构体等一次性传到线程函数中。

dwCreationFlags:该参数指明创建线程后的线程状态,在创建线程后可以让线程立刻执行(这里的立即执行的意思是不会受人为的去让它处于等待状态),也可以让线程处于暂停状态。如果需要立刻执行,该参数设置为0;如果要让线程处于暂停状态,那么该参数设置为CREATE_SUSPENDED,待需要线程执行时调用ResumeThread()函数让线程的状态调整为等待运行的状态,然后由 CPU 分配时间片后去执行。

lpThreadId: 该参数用于返回新创建线程的线程 ID。

如果线程创建成功,该函数返回线程的句柄,否则返回NULL。创建新线程后,该线程就开始启动执行了。但如果在dwCreationFlags中使用了CREATE_SUSPENDED参数,那么线程并不马上执行,而是先挂起,等到调用ResumeThread后才开始启动线程。线程的句柄需要通过CloseHandle()进行关闭,以便释放资源。

写一个简单的多线程的例子,代码如下:

代码在主线程中打印一行“main”,在创建的新线程中会打印一行“ThreadProc”。编译运行,查看其运行结果,如图1所示。

图1 多线程程序输出结果

从图1中看出,程序的输出跟预期的结果并不相同。程序的问题出在了哪里呢?每个线程都有属于自己的CPU时间片,当主线程创建新线程后,主线程的CPU时间片并未结束,它会向下继续执行。由于主线程的代码非常少,因此主线程在CPU分配的时间片中就执行完成并退出了。由于主线程的结束,意味着进程也就结束并退出了。因此,在代码中创建的线程虽然被创建了,但是根本就没有执行的机会。那么在这么短的代码中,如何保证新创建的线程在主线程结束前就能得到执行呢?或者说,主线程的运行需要等待新线程的完成才得以执行。这里需要使用WaitForSingleObject()函数,该函数的原型如下:

参数说明如下。

hHandle:该参数为要等待的对象句柄。

dwMilliseconds: 该参数指定等待超时的毫秒数,如果设为 0,则立即返回,如果设为INFINITE,则表示一直等待线程函数的返回。INFINITE 是系统定义的一个宏,其定义如下。

如果该函数失败,则返回WAIT_FAILED;如果等待的对象编程激发状态,则返回WAIT_OBJECT_0;如果等待对象变成激发状态之前,等待时间结束了,将返回WAIT_TIMEOUT。

修改上面的代码,在CreateThread()函数后面加入如下代码:

添加WaitForSingleObject()函数以后,主线程会等待新创建的线程结束再继续向下执行主线程后续的代码。这样在控制台上的输出如图2所示。

图2 主线程等待子线程的执行

WaitForSingleObject()只能等待一个线程,可是在程序中往往要创建多个线程来执行,那么如果需要等待若干个线程的完成状态的话,WaitForSingleObject()函数就无能为力了。不过,系统除了提供WaitForSingleObject()函数外,还提供了另外一个可以等待多个线程的完成状态的函数WaitForMultipleObjects(),该函数的定义如下:

该函数的参数比WaitForSingleObject()函数多2个参数,下面介绍这些参数。

nCount: 该参数用于指明想要让函数等待的线程的数量。该参数的取值范围在 1 到 MAXIMUM_WAIT _OBJECTS 之间。

lpHandles:该参数是指向等待线程句柄的数组指针。

fWaitAll: 该参数表示是否等待全部线程的状态完成,如果设置为 TRUE,则等待全部。

dwMilliseconds: 该参数与 WaitForSingleObject()函数中的 dwMilliseconds 用法相同。

WaitForSingleObject()和WaitForMultipleObjects()两个函数除了可以等待线程外,还可以等待用于多线程同步和互斥的内核对象。

在使用多线程的时候常常需要考虑和注意的问题很多。比如多线程同时对一个共享资源进行操作,通过线程需要按照一定的顺序执行等。看一个简单的多线程例子:

每个线程都有一个CPU时间片,当自己的时间片运行完成后,CPU会停止该线程的运行,并切换到其他线程去运行。当多线程同时操作一个共享资源时,这样的切换会带来隐形的问题。这里的代码比较短,在一个CPU时间片内肯定会完成,无法体现出因线程切换而产生的错误。为了达到能够因线程切换导致的错误,在代码中加入了Sleep(1),使得线程主动让出CPU,让CPU进行线程切换。在代码中,线程处理的共享资源是全局变量g_Num_One变量。主函数创建线程的代码如下:

在主函数中,通过CreateThread()创建了10个线程,每个线程都让g_Num_One自增10次,每次的增量为1。那么10个线程会使得g_Num_One的结果变成100。编译运行上面的代码,查看输出结果,如图3所示。

图3 多线程操作共享资源的错误结果

这个结果和预测的结果并不相同。为什么会产生这种不同呢?这里进行一次模拟分析。为了方便分析,把线程的数量缩小为两个线程,分别是A线程和B线程。

① g_Num_One的初始值为0。

② 当A线程中执行nTmp =g_Num_One和nTmp++后(此时nTmp的值为1),因为Sleep(1)的原因发生了线程切换,此时g_Num_One的初始值仍然为0。

③ 当B线程中执行nTmp = g_Num_One和nTmp++后(此时nTmp的值也为1),因为Sleep(1)的原因又发生了线程切换。

④ A线程执行g_Num_One = nTmp,此时g_Num_One的值为1,接着执行下一次循环中的nTmp =g_Num_One和nTmp++的操作,又进行切换。

⑤ B线程执行g_Num_One = nTmp,此时g_Num_One的值为1。

到第⑤步时,不继续往下分析了,已经可以看出原因。g_Num_One的值是最后一次nTmp进行赋值后的值(线程中的局部变量属于线程内私有的,虽然是同一个线程函数,但是nTmp在每个线程中是私有的)。

解决该问题,这里使用的是临界区。临界区对象是一个CRITICAL_SECTION的数据结构,Windows操作系统使用该数据结构对关键代码进行保护,以确保多线程下的共享资源。在同一时间内,Windows只允许一个线程进入临界区。

临界区的函数有4个,分别是初始化临界区对象(InitializeCriticalSection())、进入临界区(EnterCriticalSection())、离开临界区(LeaveCriticalSection())和删除临界区对象(DeleteCriticalSection())。临界区很好的保护了共享资源,临界区在现实生活中有很多类似的例子。比如,在进行体检的时候,一个体检室内只有一个体检医生,体检医生会叫一个患者进去体检,这时其他人是不能进入的,当这个患者离开后,下一个患者才可以进入。这里体检医生就是一个共享的资源,而每个体检的患者是多个不同的线程。临界区就是以类似的方式保护了共享资源不被破坏的。下面依次来看一下这四个函数关于临界区的函数的定义,分别如下:

这4个API函数的参数都是指向CRITICAL_SECTION结构体的指针。修改上面有问题的代码,修改后的代码如下:

编译以上代码并运行,输出结果为想要的正确结果,即g_Num_One的值为100。除了使用临界区以外,对于线程的同步与互斥还有其他方法,这里就不一一进行介绍了。在开发多线程程序时,要注意多线程的同步与互斥问题。临界区对象只能用于多线程的互斥。

推荐系统

  • 微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载

    微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载

    语言:中文版系统大小:5.13GB系统类型:Win11

    微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。Win11 64位 Office办公版(免费)优化  1、保留 Edge浏览器。  2、隐藏“操作中心”托盘图标。  3、保留常用组件(微软商店,计算器,图片查看器等)。  5、关闭天气资讯。 

  • Win11 21H2 官方正式版下载_Win11 21H2最新系统免激活下载

    Win11 21H2 官方正式版下载_Win11 21H2最新系统免激活下载

    语言:中文版系统大小:4.75GB系统类型:Win11

    Ghost Win11 21H2是微软在系统方面技术积累雄厚深耕多年,Ghost Win11 21H2系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。Ghost Win11 21H2是微软最新发布的KB5019961补丁升级而来的最新版的21H2系统,以Windows 11 21H2 22000 1219 专业版为基础进行优化,保持原汁原味,系统流畅稳定,保留常用组件

  • windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载

    windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载

    语言:中文版系统大小:5.31GB系统类型:Win11

    windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载,微软win11发布快大半年了,其中做了很多次补丁和修复一些BUG,比之前的版本有一些功能上的调整,目前已经升级到最新版本的镜像系统,并且优化了自动激活,永久使用。windows11中文版镜像国内镜像下载地址微软windows11正式版镜像 介绍:1、对函数算法进行了一定程度的简化和优化

  • 微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载

    微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载

    语言:中文版系统大小:5.31GB系统类型:Win11

    微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载,微软2022年正式推出了win11系统,很多人迫不及待的要体验,本站提供了最新版的微软Windows11正式版系统下载,微软windows11正式版镜像 是一款功能超级强大的装机系统,是微软方面全新推出的装机系统,这款系统可以通过pe直接的完成安装,对此系统感兴趣,想要使用的用户们就快来下载

  • 微软windows11系统下载 微软原版 Ghost win11 X64 正式版ISO镜像文件

    微软windows11系统下载 微软原版 Ghost win11 X64 正式版ISO镜像文件

    语言:中文版系统大小:0MB系统类型:Win11

    微软Ghost win11 正式版镜像文件是一款由微软方面推出的优秀全新装机系统,这款系统的新功能非常多,用户们能够在这里体验到最富有人性化的设计等,且全新的柔软界面,看起来非常的舒服~微软Ghost win11 正式版镜像文件介绍:1、与各种硬件设备兼容。 更好地完成用户安装并有效地使用。2、稳定使用蓝屏,系统不再兼容,更能享受无缝的系统服务。3、为

  • 雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载

    雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载

    语言:中文版系统大小:4.75GB系统类型:

    雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载在系统方面技术积累雄厚深耕多年,打造了国内重装系统行业的雨林木风品牌,其系统口碑得到许多人认可,积累了广大的用户群体,雨林木风是一款稳定流畅的系统,一直以来都以用户为中心,是由雨林木风团队推出的Windows11国内镜像版,基于国内用户的习惯,做了系统性能的优化,采用了新的系统

  • 雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO

    雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO

    语言:中文版系统大小:5.91GB系统类型:Win7

    雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO在系统方面技术积累雄厚深耕多年,加固了系统安全策略,雨林木风win7旗舰版系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。win7 32位旗舰装机版 v2019 05能够帮助用户们进行系统的一键安装、快速装机等,系统中的内容全面,能够为广大用户

  • 番茄花园Ghost Win7 x64 SP1稳定装机版2022年7月(64位) 高速下载

    番茄花园Ghost Win7 x64 SP1稳定装机版2022年7月(64位) 高速下载

    语言:中文版系统大小:3.91GB系统类型:Win7

    欢迎使用 番茄花园 Ghost Win7 x64 SP1 2022.07 极速装机版 专业装机版具有更安全、更稳定、更人性化等特点。集成最常用的装机软件,集成最全面的硬件驱动,精心挑选的系统维护工具,加上独有人性化的设计。是电脑城、个人、公司快速装机之首选!拥有此系统