인프런 커뮤니티 질문&답변

namopp님의 프로필 이미지
namopp

작성한 질문수

[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part7: MMO 컨텐츠 구현 (Unity + C# 서버 연동 기초)

스킬 #1

Room내 BroardCast시 질문입니다

작성

·

309

0

룸에서 BoardCast로 패킷을 보낼때
Send시에 lock을 걸어야할 이유가 있을까요?

lock(_lock){

   임시 list에 players의 player를 넣는다

}

foeach (player in  임시 list ) {

    player.Send 호출

}

로 했을때도 문제가 없는것 같은데 
제가 발견하지 못한 문제가 있다면 어떤 문제가 있는지 궁금합니다

답변 4

0

Rookiss님의 프로필 이미지
Rookiss
지식공유자


Send 내부에서 int a = 3; 같은 변수를 만들어서 사용하면
지역 변수이고 스택 영역에 들어가기 때문에 쓰레드 경합에 안전하지만,
전역 메모리나, Heap 메모리 쪽은 항상 위험(?)이 도사리고 있습니다.

동일한 Session을 다수의 쓰레드에서 참조한다면,
현재 _sendQueue, _pendingList 등 _가 붙은 시리즈들은
Thread-Safe하지 않습니다.
따라서 현재 상태로도 lock이 반드시 필요합니다.

namopp님의 프로필 이미지
namopp
질문자

음.. 답변주신걸 다시 한번 쭉 보니
제가 질문 자체를 모호하게 드렸던것 같네요 ㅠ 죄송합니다
그리고 제가 궁금했던 내용에 대한 답변은 처음에 주셨는데 혼란만 드렸네요 ㅠ


다른분들도 혼란이 될 수 있을까봐 코드로 첨부합니다

1.HandlerMove 함수 안에 
lock 처리를 하여 플레이어 정보의 정보등을 수정 또는 가져와서 패킷을 만든뒤

2. BroadCast 함수를 호출하고
다시 내부적으로 lock 을 하면서 foreach로 순회하며 send를 하게 되는데요

이부분을 아래 처럼 변경을 해도 이상없는지에 대한 의견이였고

답변주신내용은: 

Send 내부적으로도 lock 처리가 되고 있기 때문에,
위에서 수정하신 대로 해도 무방합니다.
복사 비용이 약간 추가되지만,
반대로 쓰레드 경합 측면에서는 이점이 생기겠죠


이것으로 정리하겠습니다. 감사합니다

0

Rookiss님의 프로필 이미지
Rookiss
지식공유자

Send는 꼭 Broadcasting할 때만 호출하는게 아니고
언제 어디서든 호출할 수 있습니다.
가령 어떤 유저한테 귓말을 하는 상황이라면,
해당 유저한테 메시지 패킷을 만들어서 Send를 날려야 하는데,
대부분 SessionManager에서 세션을 찾아서 바로 Send를 꽂아주게 됩니다.
따라서 Send는 다수의 쓰레드에서 진행될 수 있기 때문에
내부적으로 어떠한 형식으로든 동기화 처리를 해줄 필요가 있습니다.
그리고 실질적으로 네트워크 라이브러리 송수신 함수들(RecvAsync, SendAsync 등)이
Thread-Safe하지 않게 설계 되었기 때문이기도 합니다.

namopp님의 프로필 이미지
namopp
질문자

친절한 답변에 다시 한번 감사드립니다 !

벌써부터 c++ 강의가 기다려지네요 ㅎ

쓸모없는 질문같지만 양해를 부탁드리며 이어서 추가 질문 드리겠습니다!
(이해가 안가는 부분들이라 확실하게 짚고 넘어가고 싶네요 ㅠ 죄송합니다)

질문 : 
귓말 처럼 바로 Send에 꽂아주기 때문에
Send가 다수의 쓰레드에서 진행이 될 수 있다고 말씀하셨는데요

현재  Send함수내부에서 사용되는 변수들이
모두 지역변수 형태로 생성되고 쓰임되는것 같아 Thread-Safe하다고 판단이 되는데
추후 Send 함수 내부에 전역적으로 접근이 될 변수들이 생겨나게 되는건가요?


0

namopp님의 프로필 이미지
namopp
질문자

감사합니다
추가적인 질문으로  있습니다.

위에 제가 질문드린대로 복사 비용을 소비하고 진행하려고 할때
Send 내부적으로 lock 필요한 이유가 잘 이해가 안갑니다

내부적으론 경합이 일어날 이유가 없어보이거든요(sendQueue에 들어갈시에 lock처리 중..)

이부분에 대해서도 다른 이유가 있을까요?

0

Rookiss님의 프로필 이미지
Rookiss
지식공유자

Send 내부적으로도 lock 처리가 되고 있기 때문에,
위에서 수정하신 대로 해도 무방합니다.
복사 비용이 약간 추가되지만,
반대로 쓰레드 경합 측면에서는 이점이 생기겠죠.

다만 Broadcast는 하나의 예시입니다.
이번에는 운 좋게 foreach 내부에서 하는 것이
Send 하나 뿐이라 Thread-Safe 해서 별 문제 없었지만
실제로 전투 컨텐츠를 작업하다 보면
그렇게 할 수 없을 때가 많습니다.
(ex. 와우의 블리자드 스킬처럼 광범위한 데미지를 모두에게 준다거나..)

namopp님의 프로필 이미지
namopp

작성한 질문수

질문하기