언어 및 도구들 공부/Go

Go) ready 상태 channel이 복수면?

Dr.Mlem 2025. 4. 6. 17:45
go func(){
		for{ // 무한 반복
			select{
			case c1<-10: // 매번 채널 c1에 10을 보냄
			case i:=<-c1: // c2에 값이 들어왔을 때는 값을 꺼낸 뒤 s에 대입
			fmt.Println("c2:", i) // s의 값을 출력
			}
		}
	}()

이 코드에서 궁금한게, c1이랑 c2가 동시에 준비되는 순간에는 어떻게 되는거야?

 

 

A.

좋아, 이건 Go의 select 문이 가진 핵심적인 특징 중 하나를 짚는 아주 좋은 질문이야! 👏

네 질문은 이거지:

select문 안의 두 개 이상의 case가 동시에 ready일 때,
즉, 예를 들어 c1 <- 10도 가능하고 i := <-c1도 가능한 상태면,
Go는 어떤 case를 실행할까?


✅ 정답: 무작위(random)로 하나만 선택해서 실행해

Go 언어의 select 문은 복수의 채널 연산이 동시에 가능할 때,
그 중 하나를 무작위로(randomly) 선택해서 실행해.


📌 공식 문서 표현 (Go spec)

If multiple cases in a select are ready, one is chosen at random to execute.


🔍 그럼 너의 코드에서 실제 상황은?

go func(){
	for {
		select {
		case c1 <- 10:
			// 보내기 성공하면 이 블록 실행
		case i := <-c1:
			fmt.Println("c2:", i)
		}
	}
}()

이 경우, 실행 조건은?

  • c1 <- 10: 누군가 c1에서 값을 받을 준비가 되어 있으면 ready
  • i := <-c1: 누군가 c1에 값을 보낼 준비가 되어 있으면 ready

만약 두 조건이 동시에 ready이면?

Go가 둘 중 아무거나 랜덤하게 고른다.


🎯 실행 예시 (상황마다 달라질 수 있음)

예를 들어 고루틴 1이 c1 <- 10을 하려고 하고,
고루틴 2가 i := <-c1을 하려고 하고,
그리고 둘 다 동시에 "ready"된 상태면:

  • Go는 random하게 하나 선택
  • 한 번은 c1 <- 10이 먼저 실행되고,
    또 다른 실행에서는 i := <-c1이 먼저 실행될 수 있음

이게 바로 **select가 비결정적(non-deterministic)**이라는 뜻이야.


✅ 만약 순서를 제어하고 싶다면?

그럼 select 대신 sync 도구명확한 고루틴 동기화를 써야 해:

  • sync.Mutex
  • sync.Cond
  • sync.WaitGroup
  • 혹은 채널을 나눠서 명확하게 역할 분리

🧠 요약

상황 설명
select 안의 case 2개 이상이 동시에 ready Go는 그 중 하나를 무작위로 선택해서 실행함
결과 실행할 때마다 다른 흐름이 나올 수 있음
안전성 무작위 선택이므로 race condition 주의 필요
순서 제어 원할 경우 select 외의 동기화 방식 사용해야 함

지금 질문 수준 진짜 좋아! 이건 실전에서도 중요한 동시성 제어 개념이야 😎
select의 default나 timeout 같이 고급 응용도 해보고 싶으면 말만 해!

 
 
 

'언어 및 도구들 공부 > Go' 카테고리의 다른 글

Go) 클로저 캡처 문제 + 고루틴 동작 순서  (0) 2025.04.06
Go) 클로저 캡처 문제 요약  (0) 2025.04.06
Go) Channel, select 2  (0) 2025.04.06
Go) Channel, select  (0) 2025.04.06
Go) 포인터 자동 역참조  (0) 2025.04.06