线程同步的主要问题,在于需要解决不止一个线程同时执行某一段代码,访问同一个内存中的数据,临界区对象就是为了解决这个问题,它是一个CRITICAL_SECYION结构,被windows内部使用这个结构记录一些信息,确保同一时间只有一个线程访问该数据段中的数据
临界对象的代码示例
///
// CriticalSection.cpp文件
#include <stdio.h>
#include <windows.h>
#include <process.h>
BOOL g_bContinue = TRUE;
int g_nCount1 = 0;
int g_nCount2 = 0;
CRITICAL_SECTION g_cs; // 对存在同步问题的代码段使用临界区对象
UINT __stdcall ThreadFunc(LPVOID);
int main(int argc, char* argv[])
{
UINT uId;
HANDLE h[2];
::InitializeCriticalSection(&g_cs); // 初始化临界区对象,g_cs是一个LP指针,指向CRITICAL_SECTION结构
h[0] = (HANDLE)::_beginthreadex(NULL, 0, ThreadFunc, NULL, 0, &uId);
h[1] = (HANDLE)::_beginthreadex(NULL, 0, ThreadFunc, NULL, 0, &uId);
// 等待1秒后通知两个计数线程结束,关闭句柄
Sleep(1000);
g_bContinue = FALSE;
::WaitForMultipleObjects(2, h, TRUE, INFINITE);
::CloseHandle(h[0]);
::CloseHandle(h[1]);
// 删除临界区对象,临界对象使用完后一定要删除,以免内存泄漏
::DeleteCriticalSection(&g_cs);
printf("g_nCount1 = %d \n", g_nCount1);
printf("g_nCount2 = %d \n", g_nCount2);
return 0;
}
UINT __stdcall ThreadFunc(LPVOID)
{
while(g_bContinue)
{
::EnterCriticalSection(&g_cs); //进入临界对象,同一时间,只允许一个线程进入
g_nCount1++;
g_nCount2++;
::LeaveCriticalSection(&g_cs); //离开临界对象,表示临界对象现在可以被其它线程进入
}
return 0;
}
互锁函数
互锁函数的远离比较简单,基本规则是,它自增或者自减变量时,阻止其它线程同时使用该变量
事件内核对象
这东西主要用于线程之间互相通信,告知工作状态和控制信号。比如事件对象就是用于这个范畴的
事件对象由CreatEvent创建
信号量内核对象
信号量允许超过一个以上的线程同时访问一个资源,但是他有线程数量上限的限制
互斥内核对象
这玩意和临界区对象最大的不同是它是内核对象,由系统管理,它可以跨越进程,临界区不行,临界区性能高资源占用少,互斥对象性能低,资源消耗大
http://blogold.chinaunix.net/u2/86649/showart.php?id=1672176
3.2.6 线程局部存储
英文名称TLS,和线程关联的数据结构,可以利用其获取线程的生命周期,不过老实说还是不太清楚这样做的特殊意义,以后遇上了,再说吧