Gof Design Pattern
동기화 패턴 : 스레드 안전 인터페이스(Synchronization Patterns : Thread Safe Interface)
copynull
2014. 2. 21. 08:03
Synchronization Patterns : Thread Safe Interface - 동기화 패턴 : 스레드 안전 인터페이스
- 멀티스레드 프로그래밍 중에서 클래스 내부의 메서드 호출로 발생되는 셀프 데드락(Self-Dead lock) 현상 방지를 위한 패턴이다.
- 동기화에 필요한 공개함수와 내부에서 사용될 내부 함수를 분리하고, 외부에서 접근하는 공개함수들에 대해서만 동기화하고 내부 함수를 세분화하여 접근하도록 한다.
동기화와 셀프 데드락(Self-Dead lock)이란?
- 동기화 : 다수의 스레드가 하나의 리소스에 대해서 동시에 접근할 경우 다른 스레드가 변경한 리소스를 또 다른 스레드가 덮어쓰거나 변경시켜버릴 가능성이 있다(Race condition). 이를 보호하기 위해서 동기화라는 작업을 통해서 적절히 공유된 리소스를 접근할때에는 하나의 스레드만 접근되도록 하는 것이다.
- 데드락 : 멀티 스레드 환경에서 어떤 스레드도 리소스에 더이상 접근이 불가능한 상태를 일컫는다.
- 셀프 데드락 : 멀티 스레드 환경에서 어떤 스레드가 이미 자신이 선점한 리소스 동기화 락을 다시 얻으려고 할때 발생된다.
Self-Dead lock 발생 코드 예제)
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
32
33
34
35
36
37
38
39
40
41
42
43
44
|
#include <list>
class CTest
{
public:
CTest(int i) : m_Id(i) {}
int GetId() const { return m_Id; }
private:
int m_Id;
};
class CTestManager : public CMultiThreadSync<CTestManager>
{
public:
~CTestManager()
{
for each (CTest* var in mList)
delete var;
mList.clear();
}
public:
void insert(CTest* i)
{
CThreadSync cs; // 첫번째 스코프 동기화
if (!search(i))
mList.push_back(i);
else
delete i;
}
bool search(CTest* i)
{
CThreadSync cs; // 두번째 스코프 동기화
for each (CTest* var in mList)
{
if (var->GetId() == i->GetId())
return true;
}
return false;
}
private:
list<CTest*> mList;
};
|
- Insert 함수를 통해 CTest 객체를 추가한다.
- Insert 함수 내부에서 먼저 멀티스레드 락 방지로 스코프 동기화를 해주고, 컨테이너에 객체가 이미 존재하는지 검사 후 없다면 추가하도록 한다.
- 여기서 문제점은 최초 insert 함수 호출시 스코프 동기화를 걸고 락이 해제되기 전에 search 함수 호출로 다시 내부에서 동기화 락을 얻는 과정에서 셀프 데드락이 발생된다.
수정 코드 다이어그램)
다이어그램에서 보듯이, insert 와 search함수들을 외부함수, 내부함수로 세분화하고 외부함수에만 스코프 동기화를 걸어주어 셀프 데드락을 해결하였다.
수정 소스 코드)
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
#include <list>
//------------------------------------------------------------------
// CTest Entity 클래스
class CTest
{
public:
CTest(int i) : m_Id(i) {}
int GetId() const { return m_Id; }
private:
int m_Id;
};
//------------------------------------------------------------------
// CTestManager 클래스 <스코프 동기화>
class CTestManager : public CMultiThreadSync<CTestManager>
{
public:
CTestManager() {}
~CTestManager()
{
for each (CTest* var in mList)
delete var;
mList.clear();
}
public:
void insert(CTest* i)
{
CThreadSync cs;
insert_i(i);
}
bool search(CTest* i)
{
CThreadSync cs;
return search_i(i);
}
private:
void insert_i(CTest* i)
{
if (!search_i(i))
mList.push_back(i);
}
bool search_i(CTest* i)
{
for each (CTest* var in mList)
{
if (var->GetId() == i->GetId())
return true;
}
return false;
}
private:
list<CTest*> mList;
};
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
CTestManager mTestManager;
mTestManager.insert(new CTest(1024));
return 0;
}
|
헤드 퍼스트 디자인 패턴:14가지 GoF 필살 패턴! - 프로그래밍 언어 | 쿠팡
쿠팡에서 헤드 퍼스트 디자인 패턴:14가지 GoF 필살 패턴! 구매하고 더 많은 혜택을 받으세요! 지금 할인중인 다른 프로그래밍 언어 제품도 바로 쿠팡에서 확인할 수 있습니다.
www.coupang.com
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."