티스토리 뷰

MFC 스레드 동기화 - 세마포, 세마포어

한정된 개수의 자우너을 여러 스레드가 접근하려고 할 때 이를 제어하는 동기화 객체

사용 가능한 리소스의 개수에 해당하는 리소스 카운트(Resource Count) 값을 유지하므로, 수행될 수 있느 스레드 개수를 조절할 수 있다.

- 세마포를 사용한 스레드 동기화 방법

1. 세마포를 생성한다. 이때 사용 가능한 자원의 개수로 리소스 카운트를 초기화 한다.
2. 리소스를 사용할 스레드는 자신이 필요한 리소스 개수만큼 Lock()을 호출하며, Lock()이 성공할 때마다 리소스 카은트 값이 감소한다. 만약, 리소스 카운트가 0인 상태에서 Lock()을 호출하면 해당 스레드는 대기한다.
3. 리소스 사용을 마친 스레드는 자신이 사용한 리소스 개수만큼 Unlock()을 호출하며, 이때마다 리소스 카운트 값이 1씩 증가한다.

- 세마포 생성 함수

CSemaphore::CSemaphore(LONG lInitialCount = 1, LONG lMaxCount = 1, LPCTSTR pstrName = NULL, LPSECURITY_ATTRIBUTES = NULL);

- lInitialCount
세마포의 초기값

- lMaxCount
세마포의 최대값, 일반적으로 lInitialCount와 lMaxCount에 같은 값을 사용한다.

- pstrName
세마포 이름, NULL 이면 이름없는(Anonymouse) 세마포가 된다. 서로 다른 프로세스에 존재하는 스레드가 세마포를 이용하여 스레드 동기화를 하려면 동일한 이름을 가진 세마포를 접근해야 한다.

- lpsaAttribute
보안 설명자와 핸들 상속에 관련된 구조체로 특별한 경우가 아니면 기본값인 NULL 을 사용한다.

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
UINT WorkThread(LPVOID pParam)
{
    CProgressCtrl* ptr = (CProgressCtrl*)pParam;
    while (1)
    {
        srand(rand() + ::GetCurrentThreadId() + time(NULL));
        ::Sleep(rand() + ::GetCurrentThreadId() + time(NULL) % 2000);
        ptr->SetPos(0);
        for (int i = 0; i < 200; i++)
        {
            ptr->SetPos(i);
            ::Sleep(10);
        }
    }    
    return 0;
}
 
class CMFCApplication7Dlg : public CDialogEx
{
...
public:
    afx_msg void OnBnClickedStart();
    CProgressCtrl m_progress1;
    CProgressCtrl m_progress3;
    CProgressCtrl m_progress4;
    CProgressCtrl m_progress5;
    CProgressCtrl m_progress6;
    CProgressCtrl m_progress2;
};
 
void CMFCApplication7Dlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_PROGRESS1, m_progress1);
    DDX_Control(pDX, IDC_PROGRESS3, m_progress3);
    DDX_Control(pDX, IDC_PROGRESS4, m_progress4);
    DDX_Control(pDX, IDC_PROGRESS5, m_progress5);
    DDX_Control(pDX, IDC_PROGRESS6, m_progress6);
    DDX_Control(pDX, IDC_PROGRESS2, m_progress2);
}
 
BEGIN_MESSAGE_MAP(CMFCApplication7Dlg, CDialogEx)
...
    ON_BN_CLICKED(IDC_START, &CMFCApplication7Dlg::OnBnClickedStart)
END_MESSAGE_MAP()
 
void CMFCApplication7Dlg::OnBnClickedStart()
{
    AfxBeginThread(WorkThread, &m_progress1);
    AfxBeginThread(WorkThread, &m_progress2);
    AfxBeginThread(WorkThread, &m_progress3);
    AfxBeginThread(WorkThread, &m_progress4);
    AfxBeginThread(WorkThread, &m_progress5);
    AfxBeginThread(WorkThread, &m_progress6);
}
 
cs

 

<세마포 적용 변경 코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <afxmt.h>
CSemaphore g_sem(22); // 전역 변수
UINT WorkThread(LPVOID pParam)
{
    CProgressCtrl* ptr = (CProgressCtrl*)pParam;
    while (1)
    {
        srand(rand() + ::GetCurrentThreadId() + time(NULL));
        ::Sleep(rand() + ::GetCurrentThreadId() + time(NULL) % 2000);
        g_sem.Lock();
        ptr->SetPos(0);
        for (int i = 0; i < 200; i++)
        {
            ptr->SetPos(i);
            ::Sleep(10);
        }
        ptr->SetPos(0);
        g_sem.Unlock();
    }    
    return 0;
}
cs

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
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