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

2007.09.29 02:32

단장 조회 수:3284 추천: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개 첨부 됨 ( / )
 
목록
번호 제목 글쓴이 날짜 조회 수
» 효율적인 동기화를 위한 아이디어 하나 단장 2007.09.29 3284
23 버텍스버퍼의 효율적인 사용 단장 2007.10.01 5100
22 NAT 홀펀칭 단장 2007.10.25 1294
21 한국운전면허를 일본운전면허로 바꾸기 [2] 단장 2007.10.26 1351
20 Nat기반 P2P 프로그래밍 단장 2007.11.21 1627
19 개인적으로 만들어 본 리눅스 게임 서버 FAQ 단장 2007.11.27 1125
18 Networking Best Practices in XBOX360 단장 2007.12.19 10896
17 일본어 날짜 단장 2008.02.19 1150
16 std::tr1 단장 2008.03.13 1848
15 제트 추력 엔진 단장 2008.04.29 1600
14 vTune 사용법 단장 2009.01.13 3234
13 Fast Bit Counting 단장 2009.02.21 1883
12 골프의 물리학 단장 2009.05.30 1681
11 Stream of Life 단장 2009.06.29 1285
10 마력 구하는 공식 단장 2013.07.11 7383
9 Windows 8.1 복구 파티션 만들기 단장 2013.11.13 6692
8 비디오 카드의 정의 단장 2013.11.30 269
7 디카 이미지 슬라이드필름처럼 보정하기 file 단장 2014.02.13 241
6 마포에서 AF되는 포서드용 렌즈들 단장 2014.02.13 436
5 빠른 1/sqrt(n) 계산방법 단장 2014.03.05 549