【thread】 即,线程,是进程中某一顺序的控制流,在单个程序中同时运行多个线程完成不同工作,称为多线程。
理解:进程是一个可执行程序,由私有虚拟地址空间、代码、数据和其它操作系统资源组成,一个应用程序可以有一个或多个进程,一个进程 可以有一个多个线程,其中一个是主线程。函数功能 初始化一个临界资源对象。
【临界资源】
临界资源是指每次仅允许一个进程访问的资源。
属于临界资源的硬件有打印机、磁带机等,软件有消息缓冲队列、变量、数组、缓冲区等。 诸进程间应采取互斥方式,实现对这种资源的共享。
每个进程中访问临界资源的那段代码称为临界区。显然,若能保证诸进程互斥地进入自己的临界区,便可实现诸进程对临界资源的互斥访问。为此,每个进程在进入临界区之前,应先对欲访问的临界资源进行检查,看它是否正被访问。如果此刻该临界资源未被访问,进程便可进入临界区对该资源进行访问,并设置它正被访问的标志;如果此刻该临界资源正被某进程访问,则本进程不能进入临界区。
在操作系统中,有临界区的概念。临界区内放的一般是被1个以上的进程或线程(以下只说进程)共用的数据。
临界区内的数据一次只能同时被一个进程使用,当一个进程使用临界区内的数据时,其他需要使用临界区数据的进程进入等待状态。
操作系统需要合理的分配临界区以达到多进程的同步和互斥关系,如果协调不好,就容易使系统处于不安全状态,甚至出现死锁现象。
【临界区】Critical Section
简介:
不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。每个进程中访问临界资源的那段代码称为临界区(Critical Section)(临界资源是一次仅允许一个进程使用的共享资源)。每次只准许一个进程进入临界区,进入后不允许其他进程进入。不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。
多个进程中涉及到同一个临界资源的临界区称为相关临界区。
程序调度法则:进程进入临界区的调度原则是:
1、如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。
2、任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。
3、进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。
4、如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。线程同步问题:
有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起(等待),并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。
临界区在使用时以CRITICAL_SECTION结构对象保护共享资源,并分别用EnterCriticalSection()和LeaveCriticalSection()函数去标识和释放一个临界区。所用到的CRITICAL_SECTION结构对象必须经过InitializeCriticalSection()的初始化后才能使用,而且必须确保所有线程中的任何试图访问此共享资源的代码都处在此临界区的保护之下。否则临界区将不会起到应有的作用,共享资源依然有被破坏的可能。
下面通过一段代码展示了临界区在保护多线程访问的共享资源中的作用。通过两个线程来分别对全局变量g_cArray[10]进行写入操作,用临界区结构对象g_cs来保持线程的同步,并在开启线程前对其进行初始化。为了使实验效果更加明显,体现出临界区的作用,在线程函数对共享资源g_cArray[10]的写入时,以Sleep()函数延迟1毫秒,使其他线程同其抢占CPU的可能性增大。如果不使用临界区对其进行保护,则共享资源数据将被破坏,而使用临界区对线程保持同步后则可以得到正确的结果。
【创建多线程许可证】:InitializeCriticalSection
初始化一个临界资源对象。
参数:
lpCriticalSection 临界资源对象指针
无返回值
【线程锁】
EnterCriticalSection; LeaveCriticalSection
多个线程操作相同的数据时,一般是需要按顺序访问的,否则会引导数据错乱,无法控制数据,变成随机变量。为解决这个问题,就需要引入互斥变量,让每个线程都按顺序地访问变量。这样就需要使用EnterCriticalSection和LeaveCriticalSection函数。
进入许可区:EnterCriticalSection参数:lpCriticalSection 类型同(临界资源对象指针)退出许可区:LeaveCriticalSection参数:lpCriticalSection 类型同(临界资源对象指针)删除许可证:DeleteCriticalSection参数:lpCriticalSection 类型同(临界资源对象指针)
【创建一个线程】CreateThread
当使用CreateProcess调用时,系统将创建一个进程和一个主线程。CreateThread将在主线程的基础上创建一个新线程
库文件名:kernel32
参数:
lpThreadAttributes:线程属性(整数型)
dwStackSize:线程栈大小,如果为0,那么默认将使用与调用该函数的线程相同的栈空间大小(整数型)
lpStartAddress:子程序子针型
lpParameter:向线程传递的参数(整数型)
dwCreationFlags :设置线程被创建后的状态,如果为0表示,创建后立即运行,如果为4,表示线程被创建后处于挂起状态。
lpThreadId:保存新线程的ID(整数型)(要传址)提供一个整数型变量,用来接收创建成功后的线程ID.线程ID在系统范围内是唯一的.如果不提供,请置0
返回值:
函数成功,返回线程句柄;函数失败返回false。
【关闭线程句柄】CloseHandle
库文件名:kernel32说明:关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等参数:hObject Long:欲关闭的一个对象的句柄返回值:Long,非零表示成功,零表示失败。
【线程挂起】SuspendThread
库文件名:kernel32
参数:hthread
参数类型:整数型
【线程恢复】ResumeThread
【临界资源对象指针】(多线程许可证)
成员:成员 DebugInfo, 整数型, , , 调试信息成员 LockCount, 整数型, , , 锁定计数成员 RecursionCount, 整数型, , , 递归计数成员 OwningThread, 整数型, , , 拥有线程成员 LockSemaphore, 整数型, , , 锁定信号量成员 SpinCount, 整数型, , , 自旋计数