Golang의 버퍼링된 채널과 버퍼링되지 않은 채널



채널에 대한 잡담



Golang의 동시성에 대해 이야기하면 Golang은 Channel라는 동시성 통신 유형을 제공합니다. 채널 자체는 고루틴 간의 통신을 돕습니다. 한 고루틴에서 다른 고루틴으로 메시지를 보내고 받을 수 있습니다. golang에는 우리가 사용할 수 있는 두 가지 유형의 채널이 있으며 이에 대해 이야기해 보겠습니다.

버퍼링되지 않은 채널


Unbuffered channel는 내부에 메시지를 저장하는initially has no capacity 채널입니다. Unbuffered channel는 고루틴 프로세스를 채널에서 차단 해제하기 위해 메시지를 채워야 합니다. 예를 들어:

package main

import (
  "fmt"
  "time"
)

func access(ch chan int) {
  time.Sleep(time.Second)
  fmt.Println("start accessing channel\n")

  for i := range ch {
    fmt.Println(i)
    time.Sleep(time.Second)
  }
}

func main() {
  ch := make(chan int)
  defer close(ch)

  go access(ch)

  for i := 0; i < 9; i++ {
    ch <- i
    fmt.Println("Filled")
  }

  time.Sleep(3 * time.Second)
}


위의 예에서 메인 함수는 ch를 하나씩 채울 때 차단됩니다. 그리고 access function는 for 루프 때문에 main function로 채워진 메시지를 하나씩 인쇄합니다.

다음은 위 예제의 출력입니다.

$ go run chan.go 
start accessing channel

0
Filled
1
Filled
2
Filled
3
Filled
4
Filled
5
Filled
6
Filled
7
Filled
8
Filled


버퍼링된 채널



버퍼링되지 않은 채널과 달리 Buffered Channel에는 내부에 메시지를 저장할 수 있는 용량이 있습니다. Buffered Channel는 하나의 메시지뿐만 아니라 정의된 용량까지 채울 수 있습니다. 예를 들어:

package main

import (
  "fmt"
  "time"
)

func access(ch chan int) {
  time.Sleep(time.Second)
  fmt.Println("start accessing channel\n")

  for i := range ch {
    fmt.Println(i)
    time.Sleep(time.Second)
  }
}

func main() {
  // only modify this line to defined the capacity
  ch := make(chan int, 3)
  defer close(ch)

  go access(ch)

  for i := 0; i < 9; i++ {
    ch <- i
    fmt.Println("Filled")
  }

  time.Sleep(3 * time.Second)
}


결과는 다음과 같습니다.

$ go run chan.go
Filled
Filled
Filled
start accessing channel

0
Filled
1
Filled
2
Filled
3
Filled
4
Filled
5
Filled
6
7
8


보시다시피 ch는 전체 용량이 될 때까지 먼저 채워진 다음 다른 고루틴이 하나씩 액세스할 수 있습니다.

차이점


Unbuffered Channel는 처음에는 용량이 없지만 Buffered Channel는 용량이 있습니다.
Unbuffered Channelit is empty and waiting to be filled 때마다 고루틴을 차단합니다. 그러나 Buffered Channelit is empty and waiting to be filled 또는 it's on its full-capacity and there's a statement that want to fill the channel 일 때 고루틴을 차단합니다.

용량




unbuffered := make(chan int)

buffered := make(chan int, 30)


비우고 채워지기를 기다리는


Both Buffered and Unbuffered 채널이 채워질 때까지 고루틴을 차단합니다. 이 경우 1초 동안 차단합니다.

func main() {
  ch := make(chan int)
  defer close(ch)

  go func(ch chan int) {
    time.Sleep(time.Second)
    ch <- 1
  }(ch)

  <-ch
}


꽉 찬 채 채널을 채우고 싶다는 진술이 있습니다.


Buffered가 전체 용량에 있고 해제되기를 기다리고 있기 때문에 ch <- 2 채널만 ch를 차단합니다. Unbuffered Channel 메시지2에 액세스하는 고루틴이 없기 때문에 이번에는 교착 상태가 되지만 채워집니다.

func main() {
  ch := make(chan int, 1)
  defer close(ch)

  go func(ch chan int) {
    time.Sleep(time.Second)
    <-ch
  }(ch)

  ch <- 1
  ch <- 2
}

좋은 웹페이지 즐겨찾기