본문 바로가기

프로그래밍 언어/Kotlin

Channel

채널은 코루틴에서 지원하는 데이터 스트림 구조를 갖고 있는 일종의 자료구조이다.

val cahnnel = Channel<T>()

 

채널에서는 데이터를 전송 및 수신 할 수 있다.

channel.send(data)
val receiveData = channel.receive()

 

이렇게만 보면 Queue와 다른점을 찾기 어려워보이지만 채널의 큰 특징에는 일시정지(Suspend)가 있다.

 

Suspend

val channel = Channel<Int>()
CoroutineScope(Dispatchers.IO).launch {
    for(i in 1..5){
        channel.send(i)
        println("$i send!")
    }
    println("send Done!")
    channel.close()
}

repeat(5){
    delay(2000L)
    println(channel.receive())
}

원래라면 위의 코드는 5번의 채널 send가 보내진 후 2초의 딜레이마다 채널을 수신 받아 출력해야 한다.

그러나 채널은 전송 후 수신할 때까지 suspend 되기 때문에 전송 → 출력 → 전송 → 출력의 방식으로 실행된다.

 

그렇다면 채널은 한 개를 전송하면 수신할 때까지 기다려야 할 까?

 

Buffer

Buffer를 설정하면 Buffer의 개수만큼 suspend 되지 않고 전송할 수 있다.

val channel = Channel<Int>(3) // 3 << Buffer 개수
CoroutineScope(Dispatchers.IO).launch {
    for(i in 1..5){
        channel.send(i)
        println("$i send!")
    }
    println("send Done!")
    channel.close()
}

repeat(5){
    Thread.sleep(5000L)
    println("receive: ${channel.receive()}")
}
/**
 1 send!
 2 send!
 3 send!
 receive: 1
 4 send!
 receive: 2
 5 send!
 send Done!
 receive: 3
 ...
**/

 


원리

채널에는 Buffer Queue와 Send Queue가 있다.

 

Buffer가 3인 경우

기본적으로 Send를 하면  Channel에 있는 BufferQueue에 데이터를 저장한다.

만약 buffer가 그림과 같이 다 찼는데 Send가 들어오면 어떻게 될 까?

 

이때 데이터는 SendQueue에 저장 된 후 Suspend를 건다.

이후 Receive로 데이터를 수집하면 Buffer가 하나 비게 되고 SendQueue에 있던 데이터가 BufferQueue로 넘어간다.

 

Buffer가 없는 경우

첫 번째 예시처럼 Buffer를 초기화 해주지 않으면 Buffer가 생기지 않는다.

val channel = Channel<T>()

이 경우 Buffer가 없기 때문에 Send를 하면 바로 SendQueue에 쌓고 Suspend가 걸리게 된다.

 

Receive를 하면 SendQueue에 있던 데이터가 수집되고, 다음 데이터는 다시 SendQueue에 쌓이는 과정이 반복된다.

 

Buffer를 무한으로?

val channel = Channel<T>(Channel.UNLIMITED)

다음과 같이 사용하면 총 2147483647개의 버퍼가 생긴다.


여러 스레드에서의 Channel 접근

만약 여러 스레드에서 하나의 Chaanel에 접근한다면 어떻게 될 까?

 

Buffer가 남아 있는 경우

만약 Buffer가 남아 있다면 Buffer에 저장이 된다.

 

Buffer가 꽉 차 있는 경우

일단 Channel의 suspend는 스레드 별로 동작한다.

 

이게 무슨 말이냐면 스레드1이 Buffer가 가득 찬 Channel에 Send를 하면

SendQueue에 데이터를 저장한 후 스레드1에 대해 일시정지를 한다.

 

즉, 스레드2와 3에 대해서는 아직 일시정지가 걸리지 않았기 때문에

스레드2가 Send를 한다면 해당 데이터 또한 SendQueue에 저장이 되고 스레드2도 suspend가 된다.

'프로그래밍 언어 > Kotlin' 카테고리의 다른 글

Flow Builder  (0) 2025.05.30
Coroutine Flow  (0) 2025.05.30
[Kotlin] Scope Function  (0) 2025.05.10
runCatching 예외 처리  (0) 2025.03.08
[Kotlin] 정렬  (0) 2024.06.11