작성
·
848
2
single thread에서 여러개의 co-routine ( 각각 서버연동을 수행 ) 을 순차적이 아닌 concurreny 하게 수행하게 할방법은 없나요?
상황
Single Thread
ㄴ co-routine (1) : 서버연동 ( 사용자 정보를 요청 )
ㄴ co-routine (2) : 서버연동 ( 회원등급 정보 요청)
테스트 결과
co-routine (1)이 실행완료 -> co-routine(2) 수행
동시적으로 서버에 요청하지 않음
CoroutineScope(Dispatchers.Default)로 설정하여 각각 쓰레드를 생성하면 동시적으로 수행되나,
이럴경우 co-routine을 사용해야 되는 의미가 필요한지 의문이 생김
결국 multi thread가 발생했다는건 context swiching이 발생한다는 뜻인데. 오히려 이럴 바에는
co-routine을 사용하지 않고 multi thread만 사용해서 해당 코드를 수행하는것고 어떤 차이가 있는지
잘 모르겠습니다.
제 의문에 대한 명쾌한 대답을 듣고 싶습니다.
답변 1
1
안녕하세요! gilson님! 정말 좋은 질문 남겨주셔서 감사합니다! 😊
결론부터 말씀드리면 가능합니다.
물론 조건이 두 가지 필요합니다! 👍 아래 다음과 같이 적어주셨는데요!
Single Thread
ㄴ co-routine (1) : 서버연동 ( 사용자 정보를 요청 )
ㄴ co-routine (2) : 서버연동 ( 회원등급 정보 요청)
테스트 결과
co-routine (1)이 실행완료 -> co-routine(2) 수행
동시적으로 서버에 요청하지 않음
위 내용을 토대로 설명드리면, 두 가지 조건은 다음과 같습니다! 😊
(1) 서버연동과 (2) 서버연동이 각각 독립적일 것
(1) 서버 연동의 결과물이 (2)에서 필요하면 안됩니다. 예를 들어 회원등급 정보를 알기 위해서는 먼저 사용자 정보를 알야아 한다면, 사용자 정보가 있어야만 회원등급 정보를 알 수 있으니 무조건 blocking이 발생할 수 밖에 없게 됩니다.
동시적으로 (concurrently) 서버에 접근하려면 각 요청이 독립적이어야만 합니다!
외부 자원를 호출하는 코드가 non-blcoking 코드일 것
혹시 스프링을 사용하신다면, RestTemplate 대신 WebClient의 non-blocking API를 사용해주셔야 합니다. (다른 non-blocking API를 사용하셔도 괜찮습니다)
만약 DB에 접근하시는거라면, DB에 접근하기 위해 기술이 blocking이 아닌지 역시 확인해보아야 합니다.
클라이언트에서 서버에 직접 접근하시는 경우도 마찬가지로, 사용하고 있으신 HTTP 호출 코드가 non-blocking 코드여야 합니다.
이 두 가지 조건을 만족시키면, 하나의 스레드에서 2개의 코루틴이 concurrently 돌아가는 것을 확인하실 수 있을겁니다!
즉, 하나의 스레드가
1번 API에 요청을 하고
놀지 않고 (blocking 되지 않고) 2번 API에 요청을 해 둔 다음
반환된 1번 결과 처리
반환된 2번 결과 처리
하는 것을 보실 수 있을 겁니다.
답변이 도움이 되었으면 좋겠습니다! 🙂 감사합니다! 🙇
아하! blocking API를 사용하셨군요!
"결론은 single thread에서는 아무리 여러개의 co-routine을 사용해도 blocking을 수행하는 기능이라면 co-routine 사이에 switching 이발생하지 않고 순차적으로 실행된다 .즉 co-routine을 사용하지 않고 일반적인 순차적인 code 를 사용하는것에 차이가 없다"
라고 말씀해주신 부분이 정확히 맞습니다.
"blocking" 코드인 경우, 해당 코드가 thread를 blocking 하고 있기 때문에
코루틴이 아무리 여러개 있더라도 코루틴을 실행시켜줄 유일한 하나의 thread는 blocking 되어 결국 순차적으로 (thread의 blocking이 해제된 다음) 실행된다
라고 봐주시면 될 것 같습니다! 🙏
굳이 굳이 따지면, blocking API를 여러개 호출해야 해서 결국 멀티스레드를 사용해야 한다면
코루틴을 이용한 멀티스레드 코드가 순수 Java concurrent API 보다 (사람에 따라) 조금 더 쉽고 간결하게 느껴질 수도 있다 정도의 차이가 있을 것 같습니다.
감사합니다 😊
답변 감사드립니다.
당연히 blocking입니다. non-blocking 메소드를 사용했다면.. block되지 않고 바로 반환되었겠죠..제 의도는 blocking 메소드를 사용했을경우에는 co-routine 에서 제공되는 delay() 나 yield()를 호출한것처럼 자동으로 co-routine이 중단되지 않는지에 대한 물음 이었습니다.
결론은 single thread에서는 아무리 여러개의 co-routine을 사용해도 blocking을 수행하는 기능이라면 co-routine 사이에 switching 이발생하지 않고 순차적으로 실행된다 .즉 co-routine을 사용하지 않고 일반적인 순차적인 code 를 사용하는것에 차이가 없다 라고 봐도 되는지요?