효율적인 동기화를 위한 아이디어 하나

2007.09.29 02:32

단장 조회 수:3306 추천:49


programming/server 2006/12/09 17:27  

서버 프로그래밍시에 동기화 처리 시 여러 가지 골치아픈 것들이 있는데, 나름대로 머리 써서 사용했던 팁 하나 소개합니다.

리스트 컨테이너 사용시, 읽는 중에 쓰게 되면 문제가 생기게 됩니다. 그래서

EnterCriticalSection(&m_CS);
읽기작업();
LeaveCriticalSection(&m_CS);

EnterCriticalSection(&m_CS);
쓰기작업();
LeaveCriticalSection(&m_CS);


이런 식으로 크리티컬섹션 같은 동기화 객체를 이용해서 동시에 접근하지 못하도록 처리합니다. 하지만 여기서 약간의 문제라고 하면 동시에 읽는 것도 안 된다는 것입니다. (참고로 stl 컨테니어들도 동시에 여러 개의 쓰레드에서 읽는 것은 가능합니다.)

서버 프로그래밍 시 모두 문제가 되는 것은 아니지만 주로 방 리스트 처리 같은 경우에는 불필요한 블럭이 생길 수 있습니다. 많은 클라이언트에서 읽기를 요청하고, 많은 쓰레드에서 읽기를 시도하지만, 하나의 쓰레드만 리스트에 접근할 수 있기 때문이죠. 그렇다고 쓰기의 빈도도 높냐고 하면 그렇지도 않은 게, 읽기에 비하면 현저하게 적기 때문입니다. (방리스트, 유저리스트, 등등등)

여기서 어떻게 하면 읽기는 동시에 접근하되, 쓰는 동안은 읽기의 접근을 막을 수 있느냐고 고민을 하게 되었습니다. 그래서 아주 완전한 형태는 아니지만, 거의 원하는 형태의 답을 얻었는데, 아래와 같습니다. (pseudo 코드니 의미만...)

int idx = m_CS_cnt++%_MAX_CS_CNT;
EnterCriticalSection(&m_CS[idx]);
읽기작업();
LeaveCriticalSection(&m_CS[idx]);


먼저 위처럼 구성했을 경우 _MAX_CS_CNT 만큼 읽기 쓰레드가 접근할 수 있게 됩니다. (엄밀하게는 m_CS_cnt 가 동기화 되지 않아서 idx가 동시에 중복되는 일은 생기지만, 그런 경우에 문제가 생기는 것은 아니라 무시가능하며, 이를 동기화 하는 것이 오히려 비효율 적일 것입니다.)
그리고 쓰기는 아래처럼 구성합니다.

int i;
for(i=0; i<_MAX_CS_CNT; i++)
  EnterCriticalSection(&m_CS[i]);
쓰기작업();
for(i=0; i<_MAX_CS_CNT; i++)
  LeaveCriticalSection(&m_CS[i]);


모든 동기화 객체를 점유한 후에 쓰기작업을 하므로 읽기 작업이 실행될 수 없을 것입니다.
(또한 쓰기 객체끼리 동기화도 먼저 동기화 객체를 점유한 쓰레드만 전부를 가질 수 있기 때문에, 문제가 생기지 않습니다.)

결국 많은 빈도수의 읽기는 동시에 작업이 이루어지며, 쓰기 작업 시에는 읽기 작업이 이루어지지 못하게 됩니다.

예전에는 비슷한 의도를 세마포어객체를 이용해서 처리했었는데, 위처럼 간단하게 처리하는 게 더 맘에 들어서 위의 방식으로 처리하고 있습니다. ( 세마포어를 이용하면 쓰기 객체끼리의 동기화는 별도로 시켜줘야 했었는데, 이 방식이 훨씬 더 단순합니다)

댓글 0

파일 첨부

여기에 파일을 끌어 놓거나 파일 첨부 버튼을 클릭하세요.

파일 크기 제한 : 0MB (허용 확장자 : *.*)

0개 첨부 됨 ( / )
 
목록
번호 제목 글쓴이 날짜 조회 수
44 R6002 floating point not loaded ??? 단장 2006.05.16 973
43 서울 시내에서 '무료'로 주차하기 단장 2007.03.06 976
42 AMD CPU 리퍼런스 테이블 단장 2005.07.11 978
41 아마추어 암호 설계자에게 주는 충고 by 브루스 슈나이어 단장 2005.12.22 983
40 Direct3D API들의 실행 사이클 단장 2005.07.15 988
39 순수 탄소 - 퓔러렌 단장 2005.07.19 989
38 비싼 카메라 이야기 단장 2005.11.21 1000
37 Mercedes-Benz, BMW, Audi 단장 2007.01.20 1030
36 음식 칼로리표 -_-;;; [3] 단장 2005.07.14 1040
35 원핸드 스트링 기본. 마운트. [1] 단장 2005.12.05 1075
34 요요회사간의 베어링 규격 단장 2005.12.05 1084
33 CPU 평균온도 단장 2005.07.13 1087
32 원진살 단장 2007.04.14 1092
31 개인적으로 만들어 본 리눅스 게임 서버 FAQ 단장 2007.11.27 1125
30 초간단 VTune 세팅법 [3] 김도완 2005.06.16 1137
29 평 <-> 평방미터 도량형 환산. 단장 2007.08.24 1146
28 일본어 날짜 단장 2008.02.19 1150
27 윈도우에서 사용하는 포트들 단장 2007.09.06 1157
26 니콜라 테슬라 단장 2005.11.26 1168
25 맥 탄생비화 (1) 단장 2005.07.04 1177