Windows 同步与互斥函数

Download Report

Transcript Windows 同步与互斥函数

Windows 同步与互斥函数
中山大学计算机科学系
陈国明
[email protected]
CreateTread
函数功能:创建一个在调用进程的地址空间中执行的线程
函数原型:
HANDLE CreateThread(LPSECURITY_ATTRIBUTES
lpThreadAttributes,
DWORD dwStackSize, LPTHREAD_START_ROUTINE
lpStartAddress,
LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD
lpThreadId);
返回值:
成功则返回新线程的句柄,否则返回NULL
参数:安全属性,为空则不使用;线程堆栈大小,0为缺省
例如:
HANDLE h_Thread;
DWORD thread_ID;
ThreadInfo thread_info;
// 假设ThreadInfo是用户
预定义结构
……
• DWORD WINAPI SubThread (void * aa)
• { int iID=(int)aa;
}
h_Thread = CreateTread(NULL, 0,
(LPTHREAD_START_ROUTINE)SubThread,(void *)i或
&thread_info, 0, &thread_ID);
•  ExitThread
• 函数功能:结束一个线程
• 函数原型:
•
VOID ExitThread(DWORD dwExitCode);
• 返回值:无
CreateMutex
• 函数功能:创建有名或无名的互斥对象
• HANDLE
•
CreateMutex( LPSECURITY_ATTRIBUTES
lpMutexAttributes, // pointer to security
attributes BOOL bInitialOwner, // flag for initial
ownership LPCTSTR lpName // pointer to
mutex-object name );
返回值:若成功则返回互斥对象句柄,若失败则
返回NULL。
HANDLE name;
name =
CreateMutex(NULL,FALSE,"aaa");
name=OpenMutex(MUTEX_ALL_ACCES
S,FALSE,"aaa")
ReleaseMutex
函数功能:放弃指定互斥对象的所有权
函数原型:BOOL
ReleaseMutex(HANDLE hMutex);
返回值:成功则返回非零值,否则返回零。
HANDLE h_Mutex;
h_Mutex = CreateMutex(NULL, FALSE,
“mutex_for_readcount”);
……
h_Mutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE,
“mutex_for_readcount”);
…
DWORD wait_for_mutex;
wait_for_mutex = WaitForSingleObject(h_Mutex, -1);
ReleaseMutex(h_Mutex);
Sleep
函数功能:对于指定的时间间隔挂起当前的
执行线程
函数原型:VOID Sleep(DWORD
dwMilliseconds);
返回值:无
WaitForMultipleObjects
函数功能:
当满足下列条件之一时返回:
(1)任意一个或全部指定对象处于信号态;(2)超时。
函数原型:
DWORD WaitForMultipleObject(DWORD ncount, CONST HANDLE
*lpHandles, BOOL fWaitAll, DWORD dwMilliseconds);
返回值:
调用成功则返回引起函数返回的事件,否则返回WAIT_FAILED。
例如:
DWORD wait_for_all;
DWORD n_thread;
// 线程数目
HANDLE h_Thread[MAX_THREAD_NUM];
……
wait_for_all = WaitForMultipleObject(n_thread, h_Thread, TRUE, -1);
WaitForSingleObject
函数功能:当下列情况之一发生时函数返回:
(1)指定对象处于信号态 (2) 超时
函数原型:
DWORD WaitForSingleObject(HANDLE
hHandle, DWORD dwMilliseconds);
返回值:调用成功则返回引起函数返回的事
件,否则返回WAIT_FAILED。
InitializeCriticalSection
• 函数功能:初始化临界区对象(临界区使
用之前必须初始化)
• 函数原型:
• VOID
InitializeCriticalSection(LPCRITICAL_SECTI
ON lpCriticalSection);
• 返回值: 无
EnterCriticalSection
• 函数功能:等待指定临界区对象的所有权。
当调用线程被赋予所有权时,该函数返回。
• 函数原型:
• VOID
EnterCriticalSection(LPCRITICAL_SECTION
lpCriticalSection);
• 返回值:无
LeaveCriticalSection
•
•
•
•
•
•
•
•
•
•
•
•
函数功能:释放指定临界区对象的所有权。
函数原型:
VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
返回值:
调用成功则返回引起函数返回的事件,否则返回WAIT_FAILED。
例如:
CRITICAL_SECTION RP_Write;
// 定义一个临界区对象
InitializeCriticalSection(&RP_Write);
……
EnterCriticalSection(&RP_Write);
……
LeaveCriticalSection(&RP_Write);
CreateSemaphore
• 函数功能:创建一个有名或无名的信号量对象
• 函数原型:
•
HANDLE
•
•
CreateSemaphore(LPSECURITY_ATTRIBUTES
lpAttributes, LONG lInitialCount, LONG
lMaximumCount, LPCTSTR lpName);
返回值:
若成功则返回信号量对象句柄,失败则返回NULL。
ReleaseSemaphore
• 函数功能:将指定信号量对象的计数增加
一个指定的数量。
• 函数原型:
• BOOL ReleaseSemaphore(HANDLE
hSemaphore, LONG lReleaseCount,
LPLONG lpPreviousCount);
• 返回值:
• 成功则返回TRUE,否则返回FALSE。
• HANDLE
name=OpenSemaphore(SEMAPHORE_ALL_ACCE
SS,FALSE,“name");
• WaitForSingleObject(name,INFINITE);
• ReleaseSemaphore(name,1,NULL);
• WaitForSingleObject(name,INFINITE);
• ReleaseMutex(name);
题目:吃苹果
• 父亲、儿子、女儿三人和一个盘子,当盘
子空时,父亲往盘中随机放苹果或香蕉,
儿子只从盘中拿苹果,女儿只从盘中拿香
蕉。
• #include<windows.h>
• #include<iostream.h>
• #include<time.h>
• static int k=0; //for father to list the order
of throwing fruit
• CRITICAL_SECTION mmutex; //用于互斥
的临界区
• HANDLE Apple_,Banana_;
线程函数:儿子行为函数
•
•
•
•
•
•
•
•
•
•
•
•
•
•
DWORD WINAPI Son(LPVOID n)
{
int i = 1;
//::OpenSemaphore(MUTEX_ALL_ACCESS,false,"apple");
while (1)
{
::WaitForSingleObject(Apple_,INFINITE);//等苹果
cout<<"Son eats "<<i<<" apples"<<endl;
LeaveCriticalSection(&mmutex);
i++;
}
::CloseHandle(Apple_);
return 0;
}
线程函数:女儿行为函数
•
•
•
•
•
•
•
•
•
•
•
•
•
•
DWORD WINAPI Daughter(LPVOID n)
{
int i = 1;
//OpenSemaphore(MUTEX_ALL_ACCESS,false,"banana");
while (1)
{
::WaitForSingleObject(Banana_,INFINITE);//等香蕉
cout<<"Daugher eats "<<i<<" bananas"<<endl;
LeaveCriticalSection(&mmutex);
i++;
}
::CloseHandle(Banana_);
return 0;
}
线程函数:父亲放水果
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
DWORD WINAPI Father(LPVOID n)
{
UINT fruit;
EnterCriticalSection(&mmutex);
fruit = rand()%2;
if (fruit == 0)
{
//盘中放入苹果
cout<<k+1<<" father produce an apple"<<endl;
k=k+1;
::ReleaseSemaphore(Apple_,1,NULL);
}
else {//盘中放入香蕉
cout<<k+1<<" father produce a banana"<<endl;
k=k+1;
::ReleaseSemaphore(Banana_,1,NULL);
}
return 0;
}
•
•
•
•
•
•
•
•
•
•
•
•
int main()
{
int j;
k=0;
HANDLE Father_[20];
Apple_ = ::CreateSemaphore(NULL,0,1,"apple");
Banana_ =::CreateSemaphore(NULL,0,1,"banana");
InitializeCriticalSection(&mmutex);
srand(time(NULL));
for (j= 0 ; j < 20; j++)
{
Father_[j]=::CreateThread(NULL,0,Father,NULL,0,0);
•
•
•
•
•
•
•
}
::CreateThread(NULL,0,Son,NULL,0,0);
::CreateThread(NULL,0,Daughter,NULL,0,0);
Sleep(1000);
WaitForMultipleObjects(20,Father_,TRUE,INFINITE);
return 0;
}
Visual C++中伪随机数生成机制
• 用VC产生随机数有两个函数,分别为rand(void)
•
•
•
和srand(seed)。
其用法是先调用srand函数,
如 srand( (unsigned)time( NULL ) )
这样可以使得每次产生的随机数序列不同。
种子相同,则计算出来的伪随机序列就是完全相
同的。要解决这个问题,需要在每次产生随机序
列前,先指定不同的种子,这样计算出来的随机
序列就不会完全相同了。以time函数值(即当前
时间)作为种子数,因为两次调用rand函数的时
间通常是不同的,这样就可以保证随机性了。
把srand(time(NULL));去掉
恢复srand(time(NULL));