线程同步
多线程的创建
windows多线程可以使用 CreateThread创建内核对象 或 C++11<thread>多线程支持创建线程。如下示例:
#include <iostream>
#include <thread>
#include <windows.h>
int g_nCount = 100;
void test()
{
while (g_nCount > 0)
{
printf("%d--%d\n", GetCurrentThreadId(), g_nCount);
g_nCount--;
Sleep(1);
}
}
int main()
{
#if 0
// C++11 的多线程支持
std::thread t1(test);
std::thread t2(test);
t1.join();
t2.join();
#else
// windows 的多线程支持(内核对象)
HANDLE hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)test, NULL, 0, NULL);
Sleep(10);
HANDLE hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)test, NULL, 0, NULL);
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hThread2, INFINITE);
CloseHandle(hThread1);
hThread1 = NULL;
CloseHandle(hThread2);
hThread2 = NULL;
#endif
system("pause");
}
运行结果:
从上例可以看到线程的访问是无序的,这就有可能导致其他线程往往会在线程处理任务结束前就去访问处理结果,导致获取到的不是处理后的数据。这时我们就需要采取一定的机制对访问限制,也就是多线程同步机制。windows 下线程同步方式常用的有:临界区、互斥区、事件、信号量四种方式。
临界区(CRITICAL_SECTION)、互斥量(Mutex)、信号量(Semaphore)、事件(Event)的区别
临界区
临界资源是一次仅允许一个进程使用的共享资源。各进程采取互斥的方式,实现共享的资源称作临界资源。属于临界资源的硬件有,打印机,磁带机等;软件有消息队列,变量,数组,缓冲区等。诸进程间采取互斥方式,实现对这种资源的共享。
每个进程中访问临界资源的那段代码称为临界区(critical section)。每次只允许一个进程进入临界区,如果一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。
不论是硬件临界资源还是软件临界资源,多个进程必须互斥的对它进行访问。多个进程涉及到同一个临界资源的的临界区称为相关临界区。使用临界区时,一般不允许其运行时间过长,只要运行在临界区的线程还没有离开,其他所有进入此临界区的线程都会被挂起而进入等待状态,并在一定程度上影响程序的运行性能。
注意:临界区只能用于对同一进程内的线程进行同步。
(1) 初始化临界区锁
首先要声明 CRITICAL_SECTION 类型的变量。在使用临界区之前必须调用 InitializeCriticalSection 或 InitializeCriticalSectionAndSpinCount 完成初始化对象。