众所周知通过CRITICAL_SECTION可以对多个线程同步,然而加锁和解锁的次数不匹配将导致死锁:


[cpp] view plaincopy


  1. class CLock
  2. {
  3. public:
  4. CLock()
  5. {
  6. InitializeCriticalSection(&m_cs);
  7. }

  8. ~CLock()
  9. {
  10. DeleteCriticalSection(&m_cs);
  11. }

  12. void Lock()
  13. {
  14. EnterCriticalSection(&m_cs);
  15. }

  16. void Unlock()
  17. {
  18. LeaveCriticalSection(&m_cs);
  19. }
  20. private:
  21. CRITICAL_SECTION m_cs;
  22. };

[cpp] view plaincopy


  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3. unsigned ThreadId1, ThreadId2;
  4. HANDLE hThread1, hThread2;
  5. hThread1 = (HANDLE)_beginthreadex(0, 0, ThreadFun, NULL, 0, &ThreadId1);
  6. Sleep(1000);
  7. hThread2 = (HANDLE)_beginthreadex(0, 0, ThreadFun, NULL, 0, &ThreadId2);

  8. getchar();

  9. InterlockedCompareExchange(&gExit, 1, gExit);
  10. WaitForSingleObject(hThread1, -1);
  11. WaitForSingleObject(hThread2, -1);

  12. return 0;
  13. }




1、线程A加锁两次、解锁一次,将导致线程B一直不能获得锁:



[cpp] view plaincopy


  1. long gExit = 0;
  2. CLock gLock;

  3. unsigned int _stdcall ThreadFun(void* argv)
  4. {
  5. while (true)
  6. {
  7. gLock.Lock();
  8. gLock.Lock();
  9. if (InterlockedCompareExchange(&gExit, gExit, 0))
  10. {
  11. return 0;
  12. gLock.Unlock();
  13. }

  14. printf("Thread(%d) is Running\n", GetCurrentThreadId());

  15. gLock.Unlock();
  16. //gLock.Unlock();

  17. Sleep(100);
  18. }
  19. }




2、线程A加锁一次,解锁两次,当线程A下次再试图获得锁,将不能获取的到陷入死等,也将导致死锁,同理线程B。:


[cpp] view plaincopy


  1. unsigned int _stdcall ThreadFun(void* argv)
  2. {
  3. while (true)
  4. {
  5. // 加锁一次
  6. gLock.Lock();
  7. //gLock.Lock();
  8. if (InterlockedCompareExchange(&gExit, gExit, 0))
  9. {
  10. return 0;
  11. gLock.Unlock();
  12. }

  13. printf("Thread(%d) is Running\n", GetCurrentThreadId());

  14. // 解锁两次,下次gLock.Lock()将陷入死等
  15. gLock.Unlock();
  16. gLock.Unlock();

  17. Sleep(100);
  18. }
  19. }



3、解决,可以定义一个自动获得锁,保证加锁和解锁完全匹配:



[cpp] view plaincopy


  1. class AutoLock
  2. {
  3. public:
  4. AutoLock()
  5. {
  6. m_lock.Lock();
  7. }
  8. ~AutoLock()
  9. {
  10. m_lock.Unlock();
  11. }

  12. private:
  13. CLock m_lock;

  14. private:
  15. AutoLock(const AutoLock& lock);
  16. AutoLock& operator=(const AutoLock& lock);
  17. };

[cpp] view plaincopy


  1. unsigned int _stdcall ThreadFun(void* argv)
  2. {
  3. while (true)
  4. {
  5. AutoLock auto_lock;
  6. if (InterlockedCompareExchange(&gExit, gExit, 0))
  7. {
  8. return 0;
  9. }

  10. printf("Thread(%d) is Running\n", GetCurrentThreadId());

  11. Sleep(100);
  12. }
  13. }

4、后记:以上是最简单的锁实现,加锁和解锁往往导致效率低下,以此改进,使用读写锁、闩锁等不同的加锁粒度来提升性能。