一、Critical Section
Critical section(临界区)用来实现“排他性占有”。适用范围是单一进程 的各线程之间。它是:
- 一个局部性对象,不是一个核心对象。
- 快速而有效率。
- 不能够同时有一个以上的 critical section 被等待。
- 无法侦测是否已被某个线程放弃。
例子
#include <iostream>
#include <process.h>
#include <afxmt.h>
using namespace std;
CRITICAL_SECTION cs;//定义临界区对象
int g_count = 30;
DWORD _stdcall proc1(LPVOID param)
{
while (g_count > 0)
{
EnterCriticalSection(&cs);//进入临界区
cout << "窗口1卖-->" << g_count-- << endl;
LeaveCriticalSection(&cs);//离开临界区
Sleep(100);
}
return 0;
}
DWORD _stdcall proc2(LPVOID param)
{
while (g_count > 0)
{
EnterCriticalSection(&cs);//进入临界区
cout << "窗口2卖-->" << g_count-- << endl;
LeaveCriticalSection(&cs);//离开临界区
Sleep(100);
}
return 0;
}
int main()
{
HANDLE handle_array[2];
InitializeCriticalSection(&cs);//初始化临界区
handle_array[0] = CreateThread(NULL, 0, proc1, NULL, 0, NULL);
handle_array[1] = CreateThread(NULL, 0, proc2, NULL, 0, NULL);
WaitForMultipleObjects(2, handle_array, true, INFINITE);
DeleteCriticalSection(&cs);//删除临界区
system("pause");
return 0;
}
二、Mutex
Mutex 是一个核心对象,可以在不同的线程之间实现“排他性占有”,甚 至即使那些线程分属不同进程。它是:
- 一个核心对象。
- 如果拥有 mu tex 的那个线程结束,则会产生一个 “abandoned” 错 误信息。
- 可以使用 Wait...() 等待一个 mu tex。
- 可以具名,因此可以被其他进程开启。
- 只能被拥有它的那个线程释放(released)。
例子
#include <iostream>
#include <process.h>
#include <afxmt.h>
using namespace std;
HANDLE g_mutex;//定义锁对象
int g_count = 30;
DWORD _stdcall proc1(LPVOID param)
{
while (g_count > 0)
{
WaitForSingleObject(g_mutex, INFINITE);//等待锁
cout << "窗口1卖-->" << g_count-- << endl;
ReleaseMutex(g_mutex);//释放锁
Sleep(100);
}
return 0;
}
DWORD _stdcall proc2(LPVOID param)
{
while (g_count > 0)
{
WaitForSingleObject(g_mutex, INFINITE);//等待锁
cout << "窗口2卖-->" << g_count-- << endl;
ReleaseMutex(g_mutex);//释放锁
Sleep(100);
}
return 0;
}
int main()
{
HANDLE handle_array[2];
g_mutex = CreateMutex(NULL, false, NULL);//创建锁
handle_array[0] = CreateThread(NULL, 0, proc1, NULL, 0, NULL);
handle_array[1] = CreateThread(NULL, 0, proc2, NULL, 0, NULL);
WaitForMultipleObjects(2, handle_array, true, INFINITE);
CloseHandle(g_mutex);//关闭锁
system("pause");
return 0;
}
三、Semaphore
Semaphore 被用来追踪有限的资源。它是:
- 一个核心对象。
- 没有拥有者。
- 可以具名,因此可以被其他进程开启。
- 可以被任何一个线程释放(released)。
例子
#include <iostream>
#include <process.h>
#include <afxmt.h>
using namespace std;
HANDLE g_semaphore;//信号量
int g_count = 30;
DWORD _stdcall proc1(LPVOID param)
{
while (g_count > 0)
{
WaitForSingleObject(g_semaphore, INFINITE);//进入临界区
cout << "窗口1卖-->" << g_count-- << endl;
ReleaseSemaphore(g_semaphore, 1, NULL);//离开临界区
Sleep(100);
}
return 0;
}
DWORD _stdcall proc2(LPVOID param)
{
while (g_count > 0)
{
WaitForSingleObject(g_semaphore, INFINITE);//进入临界区
cout << "窗口2卖-->" << g_count-- << endl;
ReleaseSemaphore(g_semaphore, 1, NULL);//离开临界区
Sleep(100);
}
return 0;
}
int main()
{
HANDLE handle_array[2];
g_semaphore = CreateSemaphore(NULL, 1, 1, NULL);//创建信号量总数为1,并且设置为signaled状态
handle_array[0] = CreateThread(NULL, 0, proc1, NULL, 0, NULL);
handle_array[1] = CreateThread(NULL, 0, proc2, NULL, 0, NULL);
WaitForMultipleObjects(2, handle_array, true, INFINITE);
CloseHandle(g_semaphore);
system("pause");
return 0;
}
四、Event Object
Event object 通常使用于 overlapped I/O(第6章),或用来设计某些自定 义的同步对象。它是:
- 一个核心对象。
- 完全在程序掌控之下。
- 适用于设计新的同步对象。
- “要求苏醒”的请求并不会被储存起来,可能会遗失掉。
- 可以具名,因此可以被其他进程开启。
例子
#include <iostream>
#include <process.h>
#include <afxmt.h>
using namespace std;
HANDLE g_event;//事件
int g_count = 30;
DWORD _stdcall proc1(LPVOID param)
{
while (g_count > 0)
{
WaitForSingleObject(g_event, INFINITE);//进入临界区
cout << "窗口1卖-->" << g_count-- << endl;
SetEvent(g_event);//离开临界区
Sleep(100);
}
return 0;
}
DWORD _stdcall proc2(LPVOID param)
{
while (g_count > 0)
{
WaitForSingleObject(g_event, INFINITE);//进入临界区
cout << "窗口2卖-->" << g_count-- << endl;
SetEvent(g_event);//离开临界区
Sleep(100);
}
return 0;
}
int main()
{
HANDLE handle_array[2];
g_event = CreateEvent(NULL, false, false, NULL);
SetEvent(g_event);
handle_array[0] = CreateThread(NULL, 0, proc1, NULL, 0, NULL);
handle_array[1] = CreateThread(NULL, 0, proc2, NULL, 0, NULL);
WaitForMultipleObjects(2, handle_array, true, INFINITE);
CloseHandle(g_event);
system("pause");
return 0;
}
注意:关于几个函数如何使用以及每个参数什么意思,请自行百度或者查阅相关资料。