28 May 2020

java에서 비동기 처리

비동기처리


비동기 처리란?


비동기 처리란 어떤 작업을 실행하는 동안에 해당 처리가 끝나기를 기다리지 않고 다른작업을 시작할 수 있는

것을 말한다. 자바에서 비동기 처리를 할 때 알아야 하는 것 중 하나가 스레드이다.

스레드는 일련의 작업을 수행하는 rail,실 등으로 다음과 같은 프로그램도 하나의 스레드에서 작동한다

public static void main(String[] args){
    System.out.println("hello java");
}


이러한 스레드를 여러개 준비하고 각각의 스레드에서 작업을 실행해 비동기 처리를 할 수 있다.

이처럼 여러 개의 스레드로 작업을 처리하는 것을 멀티스레딩이라고 한다.


비동기 처리를 사용하는 이유


네트워크나 DB검색처럼 작업을 요청한뒤 결과를 받을때까지 기다려야 하는 경우 이를 싱글 스레드로 처리하게 되면

한 작업이 실행 중일때 다른 모든 작업이 중지 된다. 하지만 멀티스레드로 비동기 처리를 하게 되면 작업처리를 대기

하는 동안 다른 작업을 계속 진행 할 수 있다.


비동기 처리하면 속도가 무조건 싱글 스레드 보다 빠른가?


무조건 적으로 비동기 처리가 빠른 것은 아니다. 왜냐하면 스레드 생성 작업 자체가 부하가 걸리는 작업이다. 예를 들면

금방끝나는 가벼운 작업 여러개를 동시에 실행하면 각 작업 스레드를 만드는 시간이 싱글스레드에서 순차적으로 처리하는 시간

보다 오래걸리게 되면 오히려 비동기 처리하는게 손해일 수 있다.

또한 실행 중인 스레드를 전환하는 것 (context switch)도 부하가 걸리는 작업이다.


비동기 처리시 주의할 점


메모리와 캐시

비동기 처리시 주의할 점의 하나로 클래스 필드가 가리키는 값과 실제 메모리가 가리키는 값이 동일하지 않을 수 있다는

점이다. 필드가 다루는 값은 메모리에서 캐시된 값으로 여기에서 참조와 변경을 하고 적당한 시점에 실제 메모리에 값을 변경한다.

그래서 메모리에 반영전이라면 캐시값과 메모리 값은 다르게 된다. 그리고 이 캐시는 스레드 별로 있어서 특정 스레드에서 필드에

접근해 값을 변경했을때 다른 스레드에서 해당 필드를 참조하면 스레드가 가진 캐시의 이전 값을 참조하는 문제가 발생한다.


값을 캐시하는 이유? : 성능향상을 위한 것으로 필드 값이 바뀔때마다 실제 메모리에 매번 접근하기 보다 캐시 값에 접근에 처리하는
것이 유리하기 때문이다.


원자성


주의점 두번째는 일련의 처리 흐름 중간에 다른 작업이 끼어들 가능성이 있는지를 고려해야 한다는 점입니다.

싱글 스레드에서 특정 메서드를 실행하는 동안에는 다른 프로세스가 실행될 일이 없으므로 DB등 외부와 연계하는 부분을 제외

한다면 문제가 없습니다. 하지만 비동기 처리에서는 특정 메서드를 실행하는 동안 다른 작업이 실행되므로 필드에 접근하면 원자성

이 깨질 수 있습니다.


비동기 처리시 발생하는 문제점 대응 방안

final 제한자와 불변객체


여기서 안드로이드에서 프로그래밍을 했던 사람이라면 알 것이다. ui변경이나 retrofit으로 통신을 할때 넘기는 매개변수에 final

을 붙히지 않으면 컴파일 에러가 발생한다. 왜 멀티스레딩, 비동기 통신 등을 할때 final을 강제할까??

비동기 처리를 하는 응용 프로그램에서 값이 변경되는 필드나 상태가 변경되는 객체를 다루면 예상치 못한 버그가 생길 수 있다.

위에서 설명한것 처럼 프로그램은 자기 스레드의 캐시 값만을 보기 때문에 비동기 처리 시에 가변 필드나 객체를 다룬다는 것은

같은 필드나 객체가 스레드에 의해 다른 캐시 값을 가질 위험이 있다.

또한, 가변 필드나 객체를 여러 스레드에서 다루는 것은 처리 도중에 다른 스레드의 처리 때문에 값이 변경돼 의도한 결과를 얻지

못할 가능성도 있다. 이러한 이유들로 필드에 final을 붙혀 불변객체로 만들어 전달하는 것이다.


Tags:
0 comments