WIN32多线程程序设计学习笔记(第四章 上)

原创 2004年03月30日 19:18:00
 

WIN32多线程程序设计学习笔记(第四章上)

 

到目前为止,我已经知道如何创建线程,销毁线程及如何判断一个线程是否结束了;但运用线程,管理线程,如何使线程按自己意愿正确运行才是多线程程序设计的重点及难点。

 

大家知道,线程具有并发性,在同一时间段会存在多个线程,当这些线程同时存取同一数据时,就会有问题。就像在超市储物品一样,来的时候物品箱是空,转身拿物品准备储的时候,发现物品箱已被占用了。这时,物品箱就是我所说的同一数据,人指的就是线程了。

 

那么,如何让线程彼此互相合作,互不干扰呢?------协调线程的工作是由同步机制来完成的。正如书上所说:“有放多种同步机制可以运用。使用哪一种则完全视欲解决的问题而定。这些同步机制还能用各种方式组合在一起运用,以产生更精密的机制”。

 

首先,让我们看看最容易使用的一个同步机制;它包含同步机制的设计思想,拿握了它也就可以不费什么劲拿握其它的同步机制了。

1 Critical Sections(关键区域、临界区域)

程序片段:

      CRITICAL_SECTION       gBoxKey  ;

       DWORD WINAPI ThreadFun(LPVOID n)

       {

              //进入关键区域(情景:关上物品箱,拨下钥匙)

             EnterCreiticalSection (&gBoxKey ) ;1

                    //处理一些不可分割的操作。。。。。

                    //(情景:转身拿物品,储物品,去购物。。。。)

              //离开关键区域(情景:打开物品箱,拿出储存的物品,插上钥匙)               

             LeaveCreiticalSection (&gBoxKey) ;2

       }

 

       void main()

       {

              //初始化全局锁 (情景:生成物品箱的钥匙)

             InitializeCriticalSection( &gBoxKey ) ;             

              //产生两个线程 (情景:准备两个人抢一个物品箱)

             HANDLE hMan1 = CreateThread(NULL,0,ThreadFun,…….);

             HANDLE hMan2 = CreateThread(NULL,0,ThreadFun,…….);

 

             CloseHandle(hMan1);

             CloseHandle(hMan2);

 

              //删除全局锁 (情景:删除物品箱的钥匙)

             DeleteCriticalSection( &gBoxKey ) ;

       }

 

按照上面的程序,我在笔记开头所描述的“超市储物品”的情况是不会发生的,不会再有物品箱被人抢走的可能。由于线程的并发性,从我看到一个空箱子到我将物品的放入物品箱中的这段时间内的操作应该是不可分割的;否则,我看到的物品箱就随时会被人抢走。那么如何保证操作是连续、不可分割呢?简单:看到空箱子,关上箱子,拨下钥匙(1),这时,别人就没办法使用这个箱子了。当我不再需要箱子的时候,打开箱子,插入钥匙(2),就可以让别人使用了。上述就是多线程处理共享资源的一个基本思路。

 

2 Mutexes(互斥器)

程序片段:

      HANDLE            hBoxKey  ;

       DWORD WINAPI ThreadFun(LPVOID n)

       {

              //进入关键区域(情景:关上物品箱,拨下钥匙)

             WaitForSingleObject (hBoxKey ,INFINITE ) ;1

                    //处理一些不可分割的操作。。。。。

                    //(情景:转身拿物品,储物品,去购物。。。。)

              /离开关键区域(情景:打开物品箱,拿出储存的物品,插上钥匙)               

             ReleaseMutex ( hBoxKey ) ;2

       }

 

       void main()

       {

              //初始化全局锁 (情景:生成物品箱的钥匙)

             hBoxKey = CreateMutex(      NULL,FALSE,NULL );         

              //产生两个线程 (情景:准备两个人抢一个物品箱)

             HANDLE hMan1 = CreateThread(NULL,0,ThreadFun,…….);

             HANDLE hMan2 = CreateThread(NULL,0,ThreadFun,…….);

 

             CloseHandle(hMan1);

             CloseHandle(hMan2);

 

              //删除全局锁 (情景:删除物品箱的钥匙)

             CloseHandle( hBoxKey ) ;

       }

看到没?无论从共享资源的思路了,还是从程序代码的编制上,使用Mutexes与使用Critical Sections几乎都没有什么区别;但作为Mutexes机制的提出肯定是有其原因的;我们来看这样的一个情形,当我拿走钥匙以后,因为某些因素再也不能回来了,那么这个箱子便再也不能被使用。也就是说,进入Critical Sections线程若中途当掉了,那么别了线程是再也进不了Critical Sections(一个资源就这样浪费了),那些需要进入Critical Sections的线程会停在入口不再执行,线程永远都结束不了。

怎么办?(WaitForSingleObject解决

还记得上一章学过的WaitForSingleObject吗?上一章主要用它等待线程的结束,但这个函数的作用不仅限于此,在这里,我们再前进一小步,探究WaitForSingleObject这个函数的妙用。

原型:

DWORD WaitForSingleObject ( HANDLE hObjectDWORD time ) ;

hObject:等待对象的handle(代表一个核心对象),在上一章中代表线程handle,注意没有,hObject代表一个核心对象,也就是说,只要是核心对象,WaitForSingleObject都能处理,处理的原则是“当核心对象被激发时,函数返回”(有多少种核心对象?及核心对象对激发的定义见P76)。

在这里,我遇到了一个叫mutex核心对象,mutex对激发的定义是:“当没有任何线程拥有该mutex,而且有一个线程正以Wait…()等待mutex,该mutex就会短暂地出现激发状态,使Wait…()得以返回,那么在其它的情况,mutex处于未激发状态

 

好了,我们又进一步的了解了WaitForSingleObject函数,那么,如何解决Critical Sections所遇到的因难呢?当拥有mutex线程结束前没有调用ReleaseMutex(不管该线程是当了,还是忘记调用ReleaseMutex),那么其它正以WaitForSingleObject()等待此mutex的线程就会收到WAIT_ABANDONED_0。有了这个值,我就解开难题了。

程序片段:

DWORD      rc    =       WaitForSingleObject( hMutex ) ;

If ( rc == WAIT_OBJECT_0 )

{

             //正常的处理

}

else

{

             If ( rc == WAIT_ABANDONED_0 )

{

                   //没有正常的释放mutex(比如拥有mutex的线程死了)

}

}

 

我想,从笔记的角度来看,上面对mutex描述已经可以帮助我很快的上手使用了,至于对mutex更详细的说明,还是要看看书.(当然,希望我的这一段描述能帮助你理解mutexJ)

      

总结一下:

CRITICAL_SECTION                            Mutex核心对象

 

InitializeCriticalSection()                                 CreateMutex()

                                                                  OpenMutex()

 

EnterCriticalSection()                                   WaitForSingleObject()

 

LeaveCriticalSection()                                   ReleaseMutex()

 

DeleteCriticalSection()                                  CloseHandle()

 

附注:以上正文纯属加强记忆所做笔记,内容或有不详,甚至错误,请阅者见谅,匆见怪!!!

 

 

      

 

《机器学习》周志华第四章笔记

自己对决策树的一些理解,不一定对,权当加深印象。4.1基本流程组成:一个根节点、若干内部节点和若干叶节点;叶节点对应了不同的预测结果,我们的目的是从包含样本全集的根节点找到它到每个叶节点的路径对应一个...
  • sysu_cis
  • sysu_cis
  • 2016年07月01日 21:23
  • 1114

Linux程序设计学习笔记----多线程编程基础概念与基本操作

转载请注明出处,谢谢.
  • hu1020935219
  • hu1020935219
  • 2014年08月14日 14:22
  • 1879

周志华《机器学习》笔记:第3章 线性模型

本章概括 从最简单但也是最基础的线性模型开始研究。线性模型虽然简单,但却是基础。先研究线性、单属性的线性回归问题,在此基础上研究非线性、多属性的回归和分类问题。 第3章 线性模型 单属性...
  • yzqzoom
  • yzqzoom
  • 2016年07月10日 12:11
  • 3122

《win32多线程程序设计》学习笔记二

一、产生一个线程 1、产生一个线程(并因而成就一个多线程程序),是以CreateThread()函数作为开始。此函数原型如下: 二、使用多线程的结果 1、多线程程序无法预...
  • Explorer_day
  • Explorer_day
  • 2017年03月08日 12:31
  • 296

《win32多线程程序设计》学习笔记五

一、干净的终止一个线程 1、利用TerminateThread()放弃一个线程  注:尽量不要使用TerminateThread()函数。 2、几个可能的终止一个线程的方法  1)、使用信...
  • Explorer_day
  • Explorer_day
  • 2017年03月28日 20:52
  • 231

《win32多线程程序设计》学习笔记四

一、Critical Sections
  • Explorer_day
  • Explorer_day
  • 2017年03月23日 22:27
  • 430

转载:《Win32多线程程序设计》学习笔记 第10章 MFC 中的线程

《Win32多线程程序设计》学习笔记 第10章 MFC 中的线程 如果要在MFC程序中产生一个线程,而该线程将调用MFC函数或者使用MFC的任何数据,那么你必须以AfxBeginThre...
  • chunyexiyu
  • chunyexiyu
  • 2014年06月11日 09:14
  • 562

《Win32多线程程序设计》读书笔记(一)

1,可以使用GetExitThreadCode函数获取线程函数结束时的返回值 2,多线程程序设计成功的关键: 2.1,各线程的数据要分离开来,避免使用全局变量 2.2,不要在线程之间共享GDI对象 2...
  • passion_wu128
  • passion_wu128
  • 2013年09月05日 23:54
  • 855

win32多线程程序设计笔记(第三章)

一、复习第二章 在第二章中,讲到了两种等待线程的技术:         1)使用Sleep()函数——问题是你不可能事先知道什么事情要等待多久         2)使用busy loop,通过不断...
  • qq819853294
  • qq819853294
  • 2013年09月10日 19:19
  • 813

win32多线程程序设计笔记(第六章上)

我们知道当程序调用I/O设备处理一些事情时,让主程序停下来干等I/O的完成是没有效率的。。对这个问题有下面几种解决方法: 方法一:使用另一个线程进行I/O。问题是在主线程中操控多个线程,如何设置同步...
  • qq819853294
  • qq819853294
  • 2013年09月15日 18:54
  • 810
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:WIN32多线程程序设计学习笔记(第四章 上)
举报原因:
原因补充:

(最多只允许输入30个字)