C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[8762] Re:[새로운 질문]세마포어나 크리티컬 섹션 을 C++ Builder에서 어떻게 구현해야 합니까?
주경민 [amos] 3631 읽음    2001-07-05 09:08
음... 쓰레드 관련된 것은 뭐든지 설명이 길어지기 때문에...
간단히 크리티컬 섹션만 설명드리죠.

쓰레드 동기화 개체 중, C++Builder에서 사용하는
동기화 개체는 뮤텍스, 세마포어, 크리티컬 섹션의 3가지입니다.
뮤텍스와 세마포어는 프로세스간의 통신이 가능하지만,
크리티컬 섹션은 동일 프로세스 내에서만 사용이 가능합니다.
대신 3가지 개체 중 가장 빠르죠.

동기화 개체가 하는 일은 간단히 말해,
플랙(Flag)의 역할을 합니다. 즉, 깃발이죠.
두개 쓰레드는 이 깃발을 보고 동일한 자원을 공유합니다.

A라는 쓰레드와 B라는 쓰레드가 서로 돌고 있는데,
다른 것은 다 상관 없지만,
특정 메모리 영역만큼은 서로 공유해야 하며,
한놈이 쓰고 있는 동안 다른 놈이 함부로 건드리면 안 됩니다.
이럴 때는,
깃발 하나를 정해 두고,
A가 쓰는 동안은 깃발을 세우고, 일이 다 끝나면 깃발을 뉘이죠.
B는 다른 일을 할 동안은 깃발에 신경을 쓰지 않다가,
해당 영역을 접근할 때만 깃발을 보고,
깃발이 서 있으면 그곳에서 대기하게 됩니다.
A가 깃발을 뉘일 때까지 대기하는 것이죠.
그리고 깃발이 누우면 즉시 자기가 그 영역에 접근하면서,
곧바로 깃발을 세워 놓습니다.
그럼 자기가 그 영역을 액세스 하는 동안 다른 놈이
접근을 하지 못 할테니까요.

여기서 조금 혼란스러울텐데...
그럼 특정 메모리 영역에 표식을 하는 것인가?
그렇지 않습니다.
이 깃발은 일종의 약속일 뿐입니다.
'이 영역을 사용하기 위해서는 이 깃발을 기준으로 하자.
이 영역을 사용하려면 반드시 이 깃발을 세우고,
깃발이 세워져 있으면 이 영역에 함부로 접근하지 말자'
이런 약속이 되는 것이죠.

크리티컬 섹션은 프로세스 내에서는 전역적인 자원이 되어야 합니다.

#include <syncobjs.hpp>

TCriticalSection *cr = new TCriticalSection();

A라는 쓰레드 내에서 특정 영역을 접근하려고 합니다.
어떤 영역이든 상관 없습니다.

그냥 메모리 블럭을 대상으로 하죠.

char xxx[1000];

그럼 깃발을 세워야죠?
A라는 쓰레드에서 xxx에 접근을 합니다.

cr->Enter();
printf( xxx );
cr->Leave();

이제 B라는 쓰레드에서 xxx에 접근합니다.

cr->Enter();
strcpy( xxx, "안녕하세요" );
cr->Leave();

이렇게 구현이 되어 있습니다.
그럼 A가 xxx를 프린트 하는 동안에는 깃발이 세워지겠죠?
바로 이 순간에 B가 xxx에 데이터를 써 넣는 타이밍이 되었다고 치죠.
현재 깃발은 서 있습니다.
그렇다면 B 쓰레드의 'cr->Enter()'에서 걸리게 됩니다.
여기서 쓰레드가 잠시 Suspend 상태에 빠지게 되죠.
즉, xxx에는 접근하려고 하기 직전에 대기 상태가 되어 버리는 것입니다.

이제 A가 xxx를 다 썼습니다.
그럼 깃발을 내리죠?
이때 B의 Suspend가 풀리면서 곧바로 다음 줄인 xxx를 쓰는 곳으로 들어갑니다.

만약 크리티컬 섹션을 안 써서 이 메모리가 보호되지 않았다면
어떻게 될까요?
한쪽에서 xxx에 "안녕하세요"를 다 넣기도 전에
다른 한쪽에서 xxx를 가져다 뿌려 버릴 수도 있습니다.
그럼 "안녕df닝sfㅓ민ㅇ러sdㅣ머..." 뭐... 이따위 메시지가 찍힐지도 모르죠.
널문자조차 미처 못 들어갔을테니까 그 뒤의 개비지값이 다 찍히니까요.

사용법은 간단합니다.
주의할 점은...
반드시 같은 갯수의 Enter와 Leave가 쌍으로 존재해야 한다는 점입니다.

크리티컬 섹션은 어떤 식으로든 써도 상관 없지만...
가급적
크리티컬 섹션은 최대한 빠른 시간 내에 풀어 주는 것이 좋습니다.
즉,

cr->Enter();
printf( "크리티컬 섹션에 들어갑니다." );
printf( xxx );
printf( "크리티컬 섹션에서 빠져나갑니다." );
cr->Leave();

이런 코드는 좋지 않습니다.
어차피 보호해야 할 메모리는 xxx이니까,
이것을 사용할 때만 깃발을 세우는 편이 좋죠.
그래야 xxx를 접근하고자 하는 다른 쓰레드의 대기 시간이 짧아집니다.
위의 코드는 아래와 같이 고치는 편이 좋습니다.

printf( "크리티컬 섹션에 들어갑니다." );
cr->Enter();
printf( xxx );
cr->Leave();
printf( "크리티컬 섹션에서 빠져나갑니다." );

대충 설명이 되었으리라 봅니다.
도움이 되었기를...



mach9 님이 쓰신 글 :
: 주경민님의 답변 대단히 감사하겠습니다...
: 그런데,
: 세마포어나 크리티컬 섹션 을 C++ Builder에서 어떻게 구현해야 합니까?
: 답변 주시면 고맙겠습니다.
:
:
: 주경민 님이 쓰신 글 :
: : 일단 몇가지 문제가 보이는군요.
: : 물론 이 문제가 실제 치명적인 문제로 연결될지는 모르겠지만,
: : 일단 점검해 봐야 할 것 같습니다.
: :
: : 1. 통신쓰레드에 너무 높은 Priority를 줬습니다.
: :    Priority 0이면, 메모리 할당/해제시에도 태스킹 포인트를 놓치지 않을 수 있습니다.
: :    2 정도로 낮추는 것이 나으리라 봅니다.
: :
: : 2. 쓰레드끼리 메모리를 공유함에도 불구하고,
: :    Thread-safe한 코드가 작성되지 못했습니다.
: :    세마포어나 크리티컬 섹션 등을 이용해서 메모리 공유시 충돌이 없어야 합니다.
: :
: : 3. 잦은 메모리 할당은 메모리 단편화를 유발시키며,
: :    윈도우의 메모리 관리자를 혼란시킵니다.
: :    또한 메모리 관리자로 하여금 잦은 메모리 정리나 스와핑을 시도하게 한다면,
: :    통신 타이밍을 놓칠 수도 있습니다.
: :    그러니 미리 충분한 양의 Queue를 고정적으로 할당하여,
: :    실험적으로 그 크기를 조절하시거나,
: :    아니면 한번에 한개 크기씩 할당하지 마시고,
: :    십수개 이상씩 할당/해제 하시는 편이 좋습니다.
: :
: : 4. 검색, 치환이 없는 단순 Log 데이터를 남기는 것이 목적이라면,
: :    DB보다는 그냥 자체 포맷의 .Log 파일 등을 만드는 편이 낫습니다.
: :         
: :
: :
:

+ -

관련 글 리스트
8742 계속해서 메모리 할당하면 메모리 충돌로 shotdown 가능성이 높아집니까 ? mach9 1345 2001/07/04
8760     Re:계속해서 메모리 할당하면 메모리 충돌로 shotdown 가능성이 높아집니까 ? 주경민 1885 2001/07/05
8761         [새로운 질문]세마포어나 크리티컬 섹션 을 C++ Builder에서 어떻게 구현해야 합니까? mach9 1798 2001/07/05
8762             Re:[새로운 질문]세마포어나 크리티컬 섹션 을 C++ Builder에서 어떻게 구현해야 합니까? 주경민 3631 2001/07/05
8772                 Re:Re:[감사의표시]세마포어나 크리티컬 섹션 을 C++ Builder에서 어떻게 구현해야 합니까? mach9 1408 2001/07/05
8745     Re:계속해서 메모리 할당하면 메모리 충돌로 shotdown 가능성이 높아집니까 ? makerjh 1553 2001/07/04
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.