-
변수의 동시성 제어에 관한 이슈 및 해결Android 2020. 10. 27. 11:01
개요
코드를 작성하다보면 여러가지 고려할 사항이 있는데요.
그 중 하나가 동시성에 관한 문제입니다. 특히 멀티 스레드 환경에서는 더욱 주의해야하는 문제인 동시성이란 무엇일까요?
동기화와 동시성 문제
멀티 스레드 환경에서는 데이터에 대한 동시 데이터 접근 문제가 발생할 수 있습니다.
하나의 데이터에 대해 특정 스레드가 쓰는 동작을 한다면 다른 스레드가 읽는 등의 동작을 할 수 있는 것이죠.
이러한 현상의 원리는 프로세스와 스레드의 구조와 관련이 있습니다.
프로세스들 간에는 이미 OS가 별도의 프로그램으로 동작하도록 알아서 처리하고 있습니다. 프로세스는 메모리에서 고유한 주소값을 가지고 있고, 다른 프로세스가 가지고 있는 주소를 침범할 수 없습니다.
반면, 스레드는 프로세스 안에 여러개가 존재합니다. 그리고 이 스레드들은 서로 공유할 수 있는 메모리 부분이 있습니다. 이 공유할 수 있는 메모리와 자원들로 인해 동기화 문제가 발생합니다.
이러한 동기화 문제를 해결하기 위해서
1. 공유할 수 있는 데이터를 원천 차단한다 -> 전역 변수 대신 지역 변수를 할당함으로써, 여러 스레드가 공유할 수 있는 자원을 없앤다.
2. 임계영역, lock, synchronized와 같이 공유되는 영역을 보호해줄 수 있는 장치를 만든다.
오늘은 여기서 1번인 전역 변수 대신 지역 변수를 사용하는 부분을 알아보겠습니다.
Paging Library와 관련한 스레드 생성과 공유자원 접근
Paging Library의 Data Source를 구현하고 있었습니다.
여기서 서버에서 데이터를 받아와야 하는 부분이 있었는데,
인자값으로 StartPage와 perPageNumber의 두 int 값을 넘겨줘야 했습니다.
처음에는 이 두 인자를 전역 변수로 사용했습니다.
왜냐하면, PositionalDataSource의 구현 메소드로 loadInitial, loadRange이 있는데 이 두 함수에서 위에서 말한 두 인자값이 필요했기 때문이죠.
이렇게 선언하고 전역 변수를 사용할 경우, 동시성 문제가 발생할 수 있습니다.
Paging Library에서 loadInitial과 loadRange 메소드를 호출할 시, 각각의 함수에서 새로운 스레드를 생성하게 됩니다. 이 때, 메소드 구조를 보시면 pageNumber, perPageNumber에 Read, Write하고 있습니다.
여기서 동시성 문제가 발생하게 됩니다. loadInitial에서 이미 값을 write하고 저장하려고 하는데, loadRange가 이전 값을 읽어들였었다면 값은 예상과는 다른 결과가 나올 수 있습니다.
예상과는 다른 결과를 산출할 가능성이 있으므로, 치명적인 버그나 오류를 야기할 수도 있는 것입니다.
특히 수치에 민감한 서비스의 경우에는 특히 이런 문제에 대해서 주의를 가져야 할 것입니다.
마치며Android 에서는 mainThread에서 네트워크 호출을 금지한다거나 장시간 작업의 경우는 모두 workerThread에서 수행하도록 요구하고 있습니다. 하지만 workerThread 간에도 동시성 문제에 대해서 주의를 기울여야합니다. 사실 loadInitail과 loadRange 메소드 모두 workerThread에서 실행되게 되있습니다. 하지만 위에서 보다시피 동시성 문제가 발생할 여지가 있죠.
RxJava나 Paging Library 외에도 많은 곳에서 스레드를 생성하고 관리합니다. 스레드 생성과 관리에서 동시성에 대해 더 주의를 할 필요가 있겠네요.
'Android' 카테고리의 다른 글
onBackPressed와 finish의 차이 (0) 2020.12.04 Fragment에서 ViewBinding 사용 시 발생할 수 있는 메모리릭 (0) 2020.11.13 Gson을 통해 API Response를 Enum으로 매핑하기 (0) 2020.09.25 [안드로이드 9.0 프로토콜 접속 변경사항] CLEARTEXT communication to XXXX not permitted by network security policy (0) 2020.07.24 SharedPreference 이야기 (0) 2020.06.19