总结一下Windows下的线程同步方法。
首先是WaitForSingleObject函数,每个方法都用到了。
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
参数
hHandle 等待对象的 handle (代表一个核心对象)。在本例中,此为线程 handle 。
dwMilliseconds 等待的最长时间。时间终了,即使 handle 尚未成为激发状态,此函数还是要返回。此值可以是 0
(代表立刻返回),也可以是 INFINITE 代表无穷等待。
1、信号量
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName
);
参数
lpAttributes 安全属性。如果是 NULL 就表示要使用默认属性。Windows 95 忽略这一参数。
lInitialCount sem aphore 的初值。必须大于或等于 0,并且小于或等于 lMaxim umCount。
lMaximumCount Sem aphore 的最大值 。 这也就是在同一时间内能够锁住 sem aphore 之线程的最多个数。
lpName Sem aphore 的名称(一个字符串)。任何线程(或进程) 都可以根据这一名称引用 到这个 semaphore。这个值可以是 NULL ,意思是产生一 个没有名字的 sem aphore。
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
参数
hSemaphore Sem aphore 的 handle 。
lReleaseCount Sem aphore 现值的增额。该值不可以是负值或 0。
lpPreviousCount 藉此传回 sem aphore 原来的现值。
#include <iostream>
#include <time.h>
#include <string>
#include <Windows.h>
using namespace std;
HANDLE msg;
string goods;
void delay()
{
int k1 = rand()%30000+1;
while (k1)
{
int k2 = rand()%30000+1;;
while(k2)
{
k2--;
}
k1--;
}
}
DWORD WINAPI func1(LPVOID p)
{
while(1)
{
WaitForSingleObject(msg,INFINITE);
string buff[5] = {"hello","friend","cool","good","greate"};
int index = rand()%5;
goods = buff[index];
cout<<"produce a msg"<<endl;
delay();
ReleaseSemaphore(msg, 1, NULL);
}
return 0;
}
DWORD WINAPI func2(LPVOID p)
{
while(1)
{
WaitForSingleObject(msg,INFINITE);
cout<<"consume a msg: "<<goods<<endl;
delay();
ReleaseSemaphore(msg, 1, NULL);
}
return 0;
}
int main()
{
srand(clock());
msg = CreateSemaphore(NULL,0,10,NULL);
ReleaseSemaphore(msg, 1, NULL);
DWORD TheadId1;
HANDLE handle1 = CreateThread(NULL, 0, func1, (LPVOID) 8, 0, &TheadId1);
if (handle1 == false)
{
cerr<<"create thread1 fail"<<endl;
return -1;
}
DWORD TheadId2;
HANDLE handle2 = CreateThread(NULL, 0, func2, (LPVOID) 8, 0, &TheadId2);
if (handle2 == false)
{
cerr<<"create thread2 fail"<<endl;
return -1;
}
WaitForSingleObject(handle1, INFINITE);
WaitForSingleObject(handle2, INFINITE);
CloseHandle(handle1);
CloseHandle(handle2);
CloseHandle(msg);
return 0;
}
2、事件
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName
);
参数
lpEventAttributes 安全属性。NULL 表示使用默认属性。该属性在Windows 95 中会被忽略。
bManualReset 如为 FALSE,表示这个 event 将在变成激发状态(因而唤醒一个线程)之后,自动重置( reset)为非激发状态。如果是 TRUE,表示不会自动重置,必须靠程序操作(调用ResetEvent() )才能将激发状态的 event 重置为非激发状态。
bInitialState 如为 TRUE ,表示这个 event 一开始处于激发状态。如为 FALSE ,则表示这个 event一开始处于非激发状态。
lpName Event 对象的名称。任何线程或进程都可以根据这个文字名称,使用这一 event 对象。
#include <iostream>
#include <time.h>
#include <string>
#include <Windows.h>
using namespace std;
HANDLE msg;
string goods;
void delay()
{
int k1 = rand()%30000+1;
while (k1)
{
int k2 = rand()%30000+1;;
while(k2)
{
k2--;
}
k1--;
}
}
DWORD WINAPI func1(LPVOID p)
{
while(1)
{
WaitForSingleObject(msg, INFINITE);
string buff[5] = {"hello","friend","cool","good","greate"};
int index = rand()%5;
goods = buff[index];
cout<<"produce a msg"<<endl;
delay();
SetEvent(msg);
}
return 0;
}
DWORD WINAPI func2(LPVOID p)
{
while(1)
{
WaitForSingleObject(msg, INFINITE);
cout<<"consume a msg: "<<goods<<endl;
delay();
SetEvent(msg);
}
return 0;
}
int main()
{
srand(clock());
msg = CreateEvent(NULL, FALSE, FALSE, NULL);
SetEvent(msg);
DWORD TheadId1;
HANDLE handle1 = CreateThread(NULL, 0, func1, (LPVOID) 8, 0, &TheadId1);
if (handle1 == false)
{
cerr<<"create thread1 fail"<<endl;
return -1;
}
DWORD TheadId2;
HANDLE handle2 = CreateThread(NULL, 0, func2, (LPVOID) 8, 0, &TheadId2);
if (handle2 == false)
{
cerr<<"create thread2 fail"<<endl;
return -1;
}
WaitForSingleObject(handle1, INFINITE);
WaitForSingleObject(handle2, INFINITE);
CloseHandle(handle1);
CloseHandle(handle2);
CloseHandle(msg);
return 0;
}
3、互斥量
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
);
参数
lpMutexAttributes 安全属性。NULL 表示使用默认的属性。这一指定在 Window s 95 中无效。
bInitialOwner 如果你希望“调用 CreateMutex() 的这个线程”拥有产生出来的 mu tex,就将此值设为 TRUE 。
lpName mu tex 的名称(一个字符串)。任何进程或线程都可以根据此名称使用这一 mu tex。 名称可以是任意字符串,只要不含反斜线(backslash,\)即可。
BOOL ReleaseMutex(
HANDLE hMutex
);
参数
hMutex 欲释放之 mu tex 的 handle 。
#include <iostream>
#include <time.h>
#include <string>
#include <Windows.h>
using namespace std;
HANDLE msg;
string goods;
void delay()
{
int k1 = rand()%30000+1;
while (k1)
{
int k2 = rand()%30000+1;;
while(k2)
{
k2--;
}
k1--;
}
}
DWORD WINAPI func1(LPVOID p)
{
while(1)
{
WaitForSingleObject(msg,INFINITE);
string buff[5] = {"hello","friend","cool","good","greate"};
int index = rand()%5;
goods = buff[index];
cout<<"produce a msg"<<endl;
delay();
ReleaseMutex(msg);
}
return 0;
}
DWORD WINAPI func2(LPVOID p)
{
while(1)
{
WaitForSingleObject(msg,INFINITE);
cout<<"consume a msg: "<<goods<<endl;
delay();
ReleaseMutex(msg);
}
return 0;
}
int main()
{
srand(clock());
msg = CreateMutex(NULL,FALSE,NULL);
DWORD TheadId1;
HANDLE handle1 = CreateThread(NULL, 0, func1, (LPVOID) 8, 0, &TheadId1);
if (handle1 == false)
{
cerr<<"create thread1 fail"<<endl;
return -1;
}
DWORD TheadId2;
HANDLE handle2 = CreateThread(NULL, 0, func2, (LPVOID) 8, 0, &TheadId2);
if (handle2 == false)
{
cerr<<"create thread2 fail"<<endl;
return -1;
}
WaitForSingleObject(handle1, INFINITE);
WaitForSingleObject(handle2, INFINITE);
CloseHandle(handle1);
CloseHandle(handle2);
CloseHandle(msg);
return 0;
}
4、临界区(线程执行无规律)
VOID InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
参数
lpCriticalSection 一 个 指 针 , 指 向 欲 被 初 始 化 的CRITICAL_SECTION 变量。这个变量应该在你的程序中定义。
VOID EnterCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
参数
lpCriticalSection 指向一个你即将锁定的 CRITICAL_SECTION 变量。
VOID LeaveCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
参数
lpCriticalSection 指向一个你即将解除锁定的 CRITICAL_SECTION 变量。
#include <iostream>
#include <time.h>
#include <string>
#include <Windows.h>
using namespace std;
CRITICAL_SECTION msg;
string goods;
void delay()
{
int k1 = rand()%30000+1;
while (k1)
{
int k2 = rand()%30000+1;;
while(k2)
{
k2--;
}
k1--;
}
}
DWORD WINAPI func1(LPVOID p)
{
while(1)
{
EnterCriticalSection(&msg);
string buff[5] = {"hello","friend","cool","good","greate"};
int index = rand()%5;
goods = buff[index];
cout<<"produce a msg"<<endl;
delay();
LeaveCriticalSection(&msg);
}
return 0;
}
DWORD WINAPI func2(LPVOID p)
{
while(1)
{
EnterCriticalSection(&msg);
cout<<"consume a msg: "<<goods<<endl;
delay();
LeaveCriticalSection(&msg);
}
return 0;
}
int main()
{
//srand(clock());
InitializeCriticalSection(&msg);
DWORD TheadId1;
HANDLE handle1 = CreateThread(NULL, 0, func1, (LPVOID) 8, 0, &TheadId1);
if (handle1 == false)
{
cerr<<"create thread1 fail"<<endl;
return -1;
}
DWORD TheadId2;
HANDLE handle2 = CreateThread(NULL, 0, func2, (LPVOID) 8, 0, &TheadId2);
if (handle2 == false)
{
cerr<<"create thread2 fail"<<endl;
return -1;
}
WaitForSingleObject(handle1, INFINITE);
WaitForSingleObject(handle2, INFINITE);
CloseHandle(handle1);
CloseHandle(handle2);
DeleteCriticalSection(&msg);
return 0;
}