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

namopp님의 프로필 이미지

작성한 질문수

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

스킬 #1

Room내 BroardCast시 질문입니다

21.06.02 00:56 작성

·

301

0

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

lock(_lock){

   임시 list에 players의 player를 넣는다

}

foeach (player in  임시 list ) {

    player.Send 호출

}

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

답변 4

0

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

2021. 06. 02. 10:44


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

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

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

2021. 06. 02. 11:11

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


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

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

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

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

답변주신내용은: 

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


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

0

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

2021. 06. 02. 10:21

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

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

2021. 06. 02. 10:34

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

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

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

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

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


0

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

2021. 06. 02. 10:07

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

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

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

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

0

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

2021. 06. 02. 09:30

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

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

namopp님의 프로필 이미지

작성한 질문수

질문하기