동기화 패턴 : 범위 잠금 (Synchronization Patterns : Scoped Locking)
Gof Design Pattern2014. 2. 21. 03:04
Synchronization Patterns : Scoped Locking - 동기화 패턴 : 범위 잠금
- 선언된 스코프의 범위 내에서만 적용되는 동기화 디자인 패턴
- 생성자, 소멸자 기능을 이용한 패턴으로써 동기화가 적용되는 범위를 스코프(범위)에서 사용되도록 한다
코드 다이어그램)
Lock 인터페이스를 정의하고 뮤텍스, 세마포어, 크리티컬 섹션 등을 상속받아 구현클래스를 정의하고, CGuard 클래스를 통해 Lock 클래스를 사용할 수 있도록 하였다.
소스코드)
Lock_Interface.h
1 2 3 4 5 6 7 8 9 10 11 12 13 | #pragma once class Lock_Interface { public: Lock_Interface() {} ~Lock_Interface(){} public: inline virtual BOOL try_acquire(LONG timeOut = 0) = 0; inline virtual VOID acquire() = 0; inline virtual VOID release() = 0; }; |
Mutex.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #pragma once class Mutex : public Lock_Interface { public: Mutex() : m_hMutex(::CreateMutex(NULL, FALSE, NULL)) {} ~Mutex() { if (m_hMutex) CloseHandle(m_hMutex); } public: inline VOID acquire() { WaitForSingleObject(m_hMutex, INFINITE); } inline VOID release() { ReleaseMutex(m_hMutex); } inline BOOL try_acquire(LONG timeOut = 0) { return WaitForSingleObject(m_hMutex, timeOut) == WAIT_OBJECT_0; } private: HANDLE m_hMutex; }; |
CriticalSection.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #pragma once class CriticalSection : public Lock_Interface { public: CriticalSection() { InitializeCriticalSection(&m_CS); } ~CriticalSection() { DeleteCriticalSection(&m_CS); } public: inline VOID acquire() { EnterCriticalSection(&m_CS); } inline VOID release() { LeaveCriticalSection(&m_CS); } inline BOOL try_acquire(LONG timeOut = 0) { return TryEnterCriticalSection(&m_CS); } private: CRITICAL_SECTION m_CS; }; |
Semaphore.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #pragma once class Semaphore : public Lock_Interface { public: Semaphore(LONG min = 1, LONG max = 1) : m_hSemaphore(::CreateSemaphore(NULL, min, max, NULL)) {} ~Semaphore() { if (m_hSemaphore) CloseHandle(m_hSemaphore); } public: inline VOID acquire() { WaitForSingleObject(m_hSemaphore, INFINITE); } inline VOID release() { ReleaseSemaphore(m_hSemaphore, 1, NULL); } inline BOOL try_acquire(LONG timeOut = 0) { return WaitForSingleObject(m_hSemaphore, timeOut) == WAIT_OBJECT_0; } private: HANDLE m_hSemaphore; }; |
CGuard.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #pragma once template <typename T = CriticalSection> class CGuard { public: CGuard(T* i) : mLock(i), bLocked(FALSE) { mLock->acquire(); bLocked = TRUE; } ~CGuard() { if (bLocked) mLock->release(); } private: T* mLock; BOOL bLocked; }; |
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | //------------------------------------------------------------------ // 동기화 잠금 테스트 클래스 template<typename T> class CTest { public: void ThreadSafe(int i) { CGuard<T> lock(&mlock); iData = i; } private: int iData; mutable T mLock; }; //------------------------------------------------------------------ // Main int _tmain(int argc, _TCHAR* argv[]) { CTest<CriticalSection> mTest; mTest.ThreadSafe(10); return 0; } |
static 키워드를 활용하여 Lock 멤버 내부에 숨기기)
위 소스에서 보듯이, 스레드 동기화가 필요한 클래스에서는 Lock 구현 객체가 반드시 내부에 선언되어 그 객체를 CGuard 동기화 처리 되는 부분에 항상 포인터로 넘겨주어야 하는 부분이 필요했었다. 이 부분을 상위 클래스의 내부 static 멤버로 숨겨서 깨끗하게 처리하는 패턴이다. ( 원본 소스 출처(1) : 정보문화사 - 온라인 게임 서버 프로그래밍 )
이 패턴은 출처(1) 소스에서 변경하여 적용한 예제이다.
예제 코드) Lock 인터페이스 이하 구현 클래스는 동일하므로 제외하도록 한다
MultiThreadSync.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #pragma once template <typename T, typename LOCK = CriticalSection> class CMultiThreadSync { public: class CThreadSync { public: CThreadSync(VOID) : bLocked(FALSE) { T::mSync.acquire(); bLocked = TRUE; } ~CThreadSync(VOID) { if (bLocked) T::mSync.release(); } private: BOOL bLocked; }; private: static LOCK mSync; }; template <typename T, typename LOCK = CriticalSection> LOCK CMultiThreadSync<T, LOCK>::mSync; |
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | //------------------------------------------------------------------ // 동기화 잠금 테스트 클래스 class CTest : CMultiThreadSync<CTest> { public: void ThreadSafe(int i) { CThreadSync cs; iData = i; } private: int iData; }; //------------------------------------------------------------------ // Main int _tmain(int argc, _TCHAR* argv[]) { CTest mTest; mTest.ThreadSafe(10); return 0; } |
'Gof Design Pattern' 카테고리의 다른 글
싱글톤 패턴 (Singleton Pattern) (0) | 2014.03.06 |
---|---|
동기화 패턴 : 스레드 안전 인터페이스(Synchronization Patterns : Thread Safe Interface) (0) | 2014.02.21 |
풀링 패턴 (Pooling Pattern) (1) | 2014.02.12 |
해석자 패턴 (Interpreter Pattern) (0) | 2014.02.08 |
방문자 패턴 (Visitor Pattern) (0) | 2014.02.04 |