해당 포스트는 "안드로이드 비동기 프로그래밍" 책의 내용을 요약한 것이다.
※ 달빅 가상 머신(DVM)
: 안드로이드는 JVM을 사용하지 않고 달빅 가상 머신(DVM)을 사용한다. 따라서 자바 소스를 자바 바이트 코드로 컴파일 한 후 DVM 위에서 실행하는 달빅 실행 파일(Dalvic execute file)로 변환한다. JVM을 사용하지 않고 DVM을 사용하는 이유는 JVM이 데스크톱/서버 환경에 최적화 되 있기 때문이다. DVM은 메모리/프로세서/전력이 제환된 안드로이드 환경에 맞게 설계되었다.
- 자이고트
: 안드로이드는 초기에 부팅될 때 자이코트(Zygote) 프로세스를 실행한다. 자이고트는 가상 머신을 구동하고 코어 라이브러리를 적재하고 다양한 공유 구조체를 초기화한다. 그런 후 소켓에 연결 대기를 함으로써 명령을 기다린다. 만약 어플을 실행하면 자이고트가 미리 가지고 있던 가상 머신 프로세스를 생성하고 Copy-On-Write 기술을 사용해 메모리를 부모와 공유하는 새로운 자식 프로세스를 생성한다. 이렇게 하면 가상 머신과 코어 라이브러리가 미리 적재되 있기 때문에 가상 머신 초기화를 위해 많은 데이터 양을 읽지 않아도 되 구동 과부하를 줄여준다. 또한 코어 라이브러리와 공용 구조체가 있는 메모리를 자이고트 및 모든 앱과 함께 공유하기 때문에 사용자가 여러 앱을 실행할 때 많은 메모리를 아낄 수 있다.
※ 스레드
- 메인 스레드
: 안드로이드 애플리케이션을 구축할 때 메인 스레드를 봉쇄하면 안 된다. 메인 스레드에서 복잡한 계산, 파일 읽기/쓰기, 네트워킹 같은 작업을 하면 스크롤이나 터치와 같은 사용자 입력이 즉시 반응할 수 없다. 사용자는 200ms 이상의 지연이 느껴지면 알아채린다. 또한 앱이 사용자 응답에 대해 5초 이내에 응답하지 않으면 ANR(Application Not Response) 가 된다. 안드로이드는 화면 다시 기르기를 초당 60 프레임, 즉 프레임당 16.67밀리초를 목표로 한다. 따라서 메인 스레드에서 16밀리초 가깝게 작업한다면 버벅거리고 렉 걸리는 결과로 이어질 것이다.
따라서 사용자와의 반응성이 유지되야 한다. 오래 걸리는 작업을 백그라운드에서 하고 메인 스레드에서 사용자 인터페이스 처리를 하되 백그라운드는 사용자와 용의한 상호작용을 위해 적절한 시간에 응답해야 한다. 또한 백그라운드와 스레드 사이에 안전하게 데이터 전달이 가능해야 하고 많은 백그라운드 작업을 동시에 수행하기 위해 여러 개의 CPU를 잘 활용해야 한다.
- 멀티 스레드
안드로이드에서 멀티 스레드를 지원하기 위한 매커니즘으로는 다음과 같이 있다. Thread, Runnable, synchronized, volatile, Executors, 원자적 래퍼 클래스(atomic wrapper class), 생성자 잠금(locking construct), 동시성 컬렉션(concurrent collection)이 있다. 멀티 스레드를 다루는 데 중요한 요소는 정확성(일관적이되 정확한 결과를 만듬), 활동성(완료를 향향 전진)이다.
a. 정확성
: 두 스레드가 a 변수에 접근해서 1을 더하는 연산을 한다고 가정하자. 정상적으로 실행이 되면 첫 번째 스레드가 a에 1을 더하고 두 번째 스레드가 a+1에 1을 더하기 때문에 a는 a+2가 되야 된다. 하지만 첫 번째 스레드가 a에 1을 더할려고 a값을 읽고 더하기 직전에 두 번째 스레드가 a의 값을 읽는다. 결국에는 첫 번째 스레드 결과로 a+1이 되고 두 번째 스레드 결과도 a+1이 되 정확한 값이 안 나오게 된다. 이러한 상황을 경쟁 조건이라고 한다. 이에 대한 해결책은 특정 자원에 동시 접근이 불가능 하도록 배제 락을 획득함으로써 상호 배제하는 것이다.
b. 활동성
: 활동성 문제는 정확성 문제를 해결하기 위해 나온 락으로 인한 부작용이라고 말할 수 있다. 하나의 자원에 접근하는 여러 스레드가 있는 데 락을 잡는 하나의 스레드만 자원에 접근 가능하다. 따라서 락을 잡지 못한 나머지 스레드는 락을 잡은 스레드가 작업을 완료될 때까지 기다려야 한다. 즉, 병목 현상이 만들어지고 지연이 발생한다. 여기서 심각한 상황이 발생할 수도 있다. 만약 락을 잡은 스레드가 락을 놓지 않으면 다른 스레드는 해당 락을 얻을 때까지 기다리게 될 수도 있다. 이런 상황을 데드락(Deadlock)라고 한다.
'안드로이드 > 비동기, 멀티스레드' 카테고리의 다른 글
6. 동시성 Service, 메신저, 로컬 서비스(Bind), 로컬 브로드캐스트 (1) | 2017.07.18 |
---|---|
5. IntentService, PendingService, 통지 (0) | 2017.07.17 |
4. Loader 기본/응용(AsyncTaskLoader, CursorLoader) (0) | 2017.07.16 |
3. Handler와 HandlerThread 기본/응용 (0) | 2017.07.15 |
2. AsyncTask 기본/응용/심화 (1) | 2017.07.13 |