해결된 질문
작성
·
124
0
안녕하세요!
ReaderWriterLock을 고정 데이터 테이블이 운영툴 등에 의해 변경될 수 있기 때문에 사용한다고 하셨는데요. 그래서 실제로 해당 사용하게 되는 상황을 가정해 봤습니다.
예를 들어 데이터 테이블 클래스 내부의 Dictionary<int, ItemInfoClass>로부터 ItemInfoClass 정보를 얻기 위해 GetItemInfoClassByID(int id)라는 함수를 만들고, 함수 안에서는 ReaderLock을 걸었다가 ItemInfoClass를 찾은 후 return과 동시에 ReaderLock을 해제하는 식으로 함수를 꾸미려고 합니다.
하지만 얻어온 ItemInfoClass 값은 참조 값이기 때문에 컨텐츠에서 사용하는 도중 언제든지 운영툴에 의해 값이 변경 될수 있다고 생각되는데요. (이미 Get을 해온 상태여서 ReaderLock이 해제 됐기 때문입니다)
그래서 저대로 쓰면 안된다는 생각이 들어서 제가 생각해본 해결방법은
1. Get함수가 return 시에 값을 복사해서 넘겨준다.
2. 컨텐츠 단에서 ReaderLock을 걸어서 값을 얻어간 컨텐츠에서 사용이 완료될때까지 ReaderLock을 풀지 않는다.
위 두개입니다.
1번은 복사하는 데이터의 양이 너무 커지거나 매번하게 되는 복사에 대한 퍼포먼스가 염려되고,
2번은 ReadLock을 해제하지 않는 실수를 범할까봐 고민이 됩니다.
실제로 실무에서는 보통 이런 경우 어떻게 처리하는지 궁금합니다.
혹은 좋은 아이디가 있으면 가르침 좀 부탁드리겠습니다 ㅠ
답변 2
1
안녕하세요 ㅎㅎ
제대로 이해하신 것이 맞고,
Lock을 걸어서 데이터가 변동될 수 있는 함수에서
참조값 (C# class, C++ pointer/reference)을 외부로 넘기는 것 자체가 치명적인 설계 오류입니다.
그리고 별다른 해결 방법은 없고 결국 위에 말씀하신 2 가지중 선택할 수밖에 없습니다.
그런데 현실적으로 아무리 운영툴로 데이터 값을 조작한다 해도,
아이템의 스탯 등 세부 옵션 등을 조절하는 경우는 없고
보너스 (각종 이벤트, 추가 경험치, 추가 아이템 등) 수준에서 조작하는 경우가 많기 때문에
정말 참조값이 변화하는 상황은 아직 본 적이 없긴 합니다.
그러니까 대부분의 상황에서는
- 추가 경험치 : int
- 추가 아이템Id: int
등의 복사 형식을 반환하는 경우가 대부분이기 때문에,
딱히 참조를 반환할 경우는 없었던 것 같네요.
그리고 운영툴로 조작되는 부분들은 별도의 class
(예를 들면 BonusItemRewardManager)로 관리하기 때문에,
당장 Item 정보에 보너스 정보를 추가하진 않고,
간접적으로 BonusItemRewardManager에서 int BonusItemId를 뱉어주고
그걸 다시 ItemData 쪽에 질의해서 아이템 정보를 추출하는 방식으로 되어 있는 경우가 많습니다.
0