方法一:临界区
两个线程共享资源,谁先获取谁使用
int num=1;
CRITICAL_SECTIONCritical; //临界区变量
unsigned long _stdcall ThreadProc1(void*lpParameter)
{
while(num<100)
{
EnterCriticalSection(&Critical); //进入临界区
cout<<"临界区1当前计数"<<num<<endl;
num++;
Sleep(100);
LeaveCriticalSection(&Critical); //出临界区
}
return0;
}
unsigned long _stdcall ThreadProc2(void*lpParameter)
{
while(num<100)
{
EnterCriticalSection(&Critical); //进入临界区
cout<<"临界区2当前计数"<<num<<endl;
num++;
Sleep(100);
LeaveCriticalSection(&Critical); //出临界区
}
return0;
}
int _tmain(int argc, _TCHAR* argv[])
{
InitializeCriticalSection(&Critical); //初始化
HANDLEhThread1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);
HANDLEhThread2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
while(true){}
DeleteCriticalSection(&Critical);
return0;
}
注意点:
此方法一个风险,如果voidfun()函数中临界区中代码出现异常,那锁就没有出来。
导致其它线程无法获得该锁而阻塞在那边。
方法二:事件触发
一个线程等待,另一个线程唤起
#include "windows.h"
HANDLE m_hEvent = NULL;
//创建,并设置为无信号状态
m_hEvent = CreateEvent(NULL, false, true, NULL);
if (NULL == m_hEvent){
return -1;
}
ResetEvent(m_hEvent);
//一个线程在等待5s或一直在等待
WaitForSingleObject(pZmq->m_hEvent, 5000);
WaitForSingleObject(pZmq->m_hEvent, INFINITE);
参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。
//另一个线程设置事件为有信号状态,第一个线程的WaitForSingleObject会立即返回。
SetEvent(m_hEvent);
方法三:临界区之进化版
.h
class CJCCriticalSection
{
public:
CJCCriticalSection();
virtual ~CJCCriticalSection();
inline void Lock();
inline void Unlock();
private:
CRITICAL_SECTION m_cs;
};
class CJCLock
{
public:
CJCLock(CJCCriticalSection& cs);
~CJCLock();
private:
CJCLock(const CJCLock&); //禁止锁拷贝
const CJCLock& operator =(const CJCLock&); //禁止赋值
private:
CJCCriticalSection &m_cs;
};
.cpp
CJCCriticalSection::CJCCriticalSection()
{
InitializeCriticalSection(&m_cs);
}
CJCCriticalSection::~CJCCriticalSection()
{
DeleteCriticalSection(&m_cs);
}
void CJCCriticalSection::Lock()
{
EnterCriticalSection(&m_cs);
}
void CJCCriticalSection::Unlock()
{
LeaveCriticalSection(&m_cs);
}
CJCLock::CJCLock(CJCCriticalSection& cs) : m_cs(cs)
{
m_cs.Lock();
}
CJCLock::~CJCLock()
{
m_cs.Unlock();
}
//如上代码即便临界区代码出现异常退出函数,锁也会被释放,其它线程不会被阻塞。
//多线程锁的是数据操作,不是锁代码,代码在多线程中互不影响。