实验二线程的实现和线程间的同步与互斥
一、目的:
1、了解在WINDOWS中线程的编程实现,掌握利用VC或DELPHI调用WINDOWS API建立线程。
2、了解在WINDOWS中线程间同步与互斥的信号量的实现,并利用该原理实现在WINDOWS下模拟实现有关经典线程同步与互斥问题。
二、内容:
1、利用VC或DELPHI在实际程序中实现线程。
2、利用VC或DELPHI实现线程的同步模拟。主要模拟以下问题(经营者和消费者、阅读者和写入者)。
三、实验要求:
实验内容中的第1小题为必作内容,第2小题可选择其一。
四、实验提示:
1、在Windows中调用API函数。
对于VC,在程序头文件应包括#include <windows.h>语句。
对于DELPHI,在程序前的USES中应包括Windows。
2、Windows系统中的线程及有关的系统调用。
Windows中的线程是内核线程,是系统的主要调度单位,提供了一系列的系统调用。CreateThread完成线程的创建,TerminateThread用于结束当前线程。SuspendThread可挂起指定的线程。ResumeThread可激活指定的线程。对于Windows来说,是用挂起计数来进行线程挂起和激活的计数的。每调用挂起一次,计数加1,反之则减1。当计数为0时,线程恢复运行。四个调用的原型及简单说明如下。
(1)、CreateThread创建线程
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, //指向安全属性结构的指针,一般为NULL。
DWORD dwStackSize, // 初始化线程的堆栈尺寸,一般为0。
LPTHREAD_START_ROUTINE lpStartAddress, // 指向线程执行体的指针。
LPVOID lpParameter, // 新线程的参数
DWORD dwCreationFlags, // 建立标志位,0:创建后立即执行,1:创建后挂起。
LPDWORD lpThreadId // 指向返回标识符的指针。
)
(2)、SuspendThread挂起指定的线程
DWORD SuspendThread(
HANDLE hThread // 线程句柄
)
(3)、ResumeThread激活指定的线程
DWORD ResumeThread(
HANDLE hThread // 线程句柄
)
(4)、TerminateThread结束线程
BOOL TerminateThread(
HANDLE hThread, // 线程句柄
DWORD dwExitCode // 线程的结束代码。一般为0。
)
3、Windows中的同步机制及相关调用。
在Windows中提供了互斥对象、信号量对象和事件对象三种同步对象和相应的系统调用,用于进程和线程的同步。另外还提供了临界区(Critical Section)对象和互斥变量访问API等。在这里,我们主要对互斥对象和信号量对象进行简单介绍。
互斥对象(Mutex)为互斥信号量,它的相关API为:Createmutex创建一个互斥信号量,Openmutex打开一个互斥信号量,Releasemutex释放一个互斥信号量,使之可用,相当于Signal操作。
信号量对象(Semaphore)为资源信号量,它的相关API为:CreateSemaphore创建一个信号量对象,OpenSemaphore打开一个信号量对象,ReleaseSemaphore释放一个信号对象。
系统中统一的等待操作WaitForSingleObject,相当于Wait操作。
七个调用的原型和简单说明如下:
(1)、Createmutex创建互斥信号量
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针,一般为NULL
BOOL bInitialOwner, // 初始化时所有权的标志位,TRUE:创建时即拥有,FALSE:创建时不拥有。
LPCTSTR lpName // 互斥信号量的名称
)
(2)、Openmutex打开互斥信号量
HANDLE OpenMutex(
DWORD dwDesiredAccess, // 操作标志位,一般为MUTEX_ALL_ACCESS
BOOL bInheritHandle, // 继承标志位,一般为FALSE
LPCTSTR lpName // 互斥信号量的名称
)
(3)、Releasemutex释放互斥信号量
BOOL ReleaseMutex(
HANDLE hMutex // 互斥信号量的句柄
)
(4)、CreateSemaphore创建信号量对象
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // 指向安全属性的指针,一般为NULL。
LONG lInitialCount, // 信号量的初始化值。
LONG lMaximumCount, // 信号量的最大值
LPCTSTR lpName // 信号量名称
)
(5)、OpenSemaphore打开一个信号量对象
HANDLE OpenSemaphore(
DWORD dwDesiredAccess, //操作标志位,一般为SEMAPHORE_ALL_ACCESS
BOOL bInheritHandle, //继承标志位,一般为FALSE
LPCTSTR lpName // 信号量对象名称
)
(6)、ReleaseSemaphore释放信号对象
BOOL ReleaseSemaphore(
HANDLE hSemaphore, // 信号对象句柄
LONG lReleaseCount, //释放的个数
LPLONG lpPreviousCount // 前一个计数的地址,一般为NULL
)
(7)、WaitForSingleObject等待操作
DWORD WaitForSingleObject(
HANDLE hHandle, // 等待的信号量的句柄
DWORD dwMilliseconds // 等待的时间,以毫秒为单位,如果永久等待,则为INFINITE
)
5、生产者和消费者、读者和写者问题模拟的说明。
生产者和消费者问题,缓冲区可以用一简单计数Count来描述,例如生产者生产了5个产品,可用Count=Count+5来描述。开始时可以用1个生产者线程和一个消费者线程。调试通过后可用多个线程。
读者和写者问题,读写过程可用输出语句来描述。