众所周知通过CRITICAL_SECTION可以对多个线程同步,然而加锁和解锁的次数不匹配将导致死锁:
- class CLock
- {
- public:
- CLock()
- {
- InitializeCriticalSection(&m_cs);
- }
- ~CLock()
- {
- DeleteCriticalSection(&m_cs);
- }
- void Lock()
- {
- EnterCriticalSection(&m_cs);
- }
- void Unlock()
- {
- LeaveCriticalSection(&m_cs);
- }
- private:
- CRITICAL_SECTION m_cs;
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- unsigned ThreadId1, ThreadId2;
- HANDLE hThread1, hThread2;
- hThread1 = (HANDLE)_beginthreadex(0, 0, ThreadFun, NULL, 0, &ThreadId1);
- Sleep(1000);
- hThread2 = (HANDLE)_beginthreadex(0, 0, ThreadFun, NULL, 0, &ThreadId2);
- getchar();
- InterlockedCompareExchange(&gExit, 1, gExit);
- WaitForSingleObject(hThread1, -1);
- WaitForSingleObject(hThread2, -1);
- return 0;
- }
1、线程A加锁两次、解锁一次,将导致线程B一直不能获得锁:
- long gExit = 0;
- CLock gLock;
- unsigned int _stdcall ThreadFun(void* argv)
- {
- while (true)
- {
- gLock.Lock();
- gLock.Lock();
- if (InterlockedCompareExchange(&gExit, gExit, 0))
- {
- return 0;
- gLock.Unlock();
- }
- printf("Thread(%d) is Running ", GetCurrentThreadId());
- gLock.Unlock();
- //gLock.Unlock();
- Sleep(100);
- }
- }
2、线程A加锁一次,解锁两次,当线程A下次再试图获得锁,将不能获取的到陷入死等,也将导致死锁,同理线程B。:
- unsigned int _stdcall ThreadFun(void* argv)
- {
- while (true)
- {
- // 加锁一次
- gLock.Lock();
- //gLock.Lock();
- if (InterlockedCompareExchange(&gExit, gExit, 0))
- {
- return 0;
- gLock.Unlock();
- }
- printf("Thread(%d) is Running ", GetCurrentThreadId());
- // 解锁两次,下次gLock.Lock()将陷入死等
- gLock.Unlock();
- gLock.Unlock();
- Sleep(100);
- }
- }
3、解决,可以定义一个自动获得锁,保证加锁和解锁完全匹配:
- class AutoLock
- {
- public:
- AutoLock()
- {
- m_lock.Lock();
- }
- ~AutoLock()
- {
- m_lock.Unlock();
- }
- private:
- CLock m_lock;
- private:
- AutoLock(const AutoLock& lock);
- AutoLock& operator=(const AutoLock& lock);
- };
- unsigned int _stdcall ThreadFun(void* argv)
- {
- while (true)
- {
- AutoLock auto_lock;
- if (InterlockedCompareExchange(&gExit, gExit, 0))
- {
- return 0;
- }
- printf("Thread(%d) is Running ", GetCurrentThreadId());
- Sleep(100);
- }
- }
4、后记:以上是最简单的锁实现,加锁和解锁往往导致效率低下,以此改进,使用读写锁、闩锁等不同的加锁粒度来提升性能。