Windows provide four functions for using critical sections. To use these functions, you must define an object of type CRITICAL_SECTION.
Key Points
1. Define a CRITICAL_SECTION object cs
2. Initialize a Critical section using InitializeCriticalSection (&cs);
3. After the critical section object has been initialized, a thread enters the critical section by calling EnterCriticalSection(&cs); No two threads can own the critical section at the same time
4. A thread leaves the critical section by calling LeaveCriticalSection (&cs);
5. When the critical section object is no longer needed, it can be deleted by the program by calling DeleteCriticalSection (&cs);
#ifndef _Lock_H_ #define _Lock_H_ #include <windows.h> /** *@description: A simple Lock implementation using windows critical section object */ namespace examples { class Lock { public: Lock() { ::InitializeCriticalSection(&m_cs); } ~Lock() { ::DeleteCriticalSection(&m_cs); } void acquire() { ::EnterCriticalSection(&m_cs); } void release() { ::LeaveCriticalSection(&m_cs); } private: Lock(const Lock&); Lock& operator=(const Lock&); CRITICAL_SECTION m_cs; }; } #endif //_Lock_H_
The program below uses Critical Section mechanism to ensure that the two threads (add thread and sub thread) operations are consistent on the shared global variable
#include <windows.h> #include <process.h> #include <iostream> #include <assert.h> #include "Lock.h" //File: CriticalSectionExample.cpp #define MAX_THREADS 2 using namespace std; static unsigned int counter = 100; static bool alive = true; static examples::Lock lock; static unsigned __stdcall sub(void *args) { while(alive) { lock.acquire(); cout << "[Sub(" << counter << ")]" << endl; counter -= 10; lock.release(); ::Sleep(500); } return 0; } static unsigned __stdcall add(void *args) { while(alive) { lock.acquire(); cout << "[Add(" << counter << ")]" << endl; counter += 10; lock.release(); ::Sleep(500); } return 0; } int main() { // create threads unsigned tadd; HANDLE hadd = (HANDLE) ::_beginthreadex(0, 0, &add, 0, CREATE_SUSPENDED, &tadd); assert(hadd != 0); unsigned tsub; HANDLE hsub = (HANDLE) ::_beginthreadex(0, 0, &sub, 0, CREATE_SUSPENDED, &tsub); assert(hsub != 0); // start threads ::ResumeThread(hadd); ::ResumeThread(hsub); ::Sleep(10000); // let threads run for 10 seconds // stop & cleanup threads alive = false; ::WaitForSingleObject(hsub, INFINITE); ::CloseHandle(hsub); ::WaitForSingleObject(hadd, INFINITE); ::CloseHandle(hadd); return 0; }
Sample Run of the Program:
If you want to dig deep into the Windows Critical Sections, refer Matt Pietrek and Russ Osterlund article on Debugging Code Deadlocks in Critical Sections Under Windows
No comments:
Post a Comment