동기화 패턴 : 범위 잠금 (Synchronization Patterns : Scoped Locking)
* 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
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;
}
|
헤드 퍼스트 디자인 패턴:14가지 GoF 필살 패턴! - 프로그래밍 언어 | 쿠팡
쿠팡에서 헤드 퍼스트 디자인 패턴:14가지 GoF 필살 패턴! 구매하고 더 많은 혜택을 받으세요! 지금 할인중인 다른 프로그래밍 언어 제품도 바로 쿠팡에서 확인할 수 있습니다.
www.coupang.com
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
'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 |