goroutine

기본정보

  • 쓰레드

  • 프로세스

고루틴

고루틴은 경량 쓰레드로 함수나 명령을 동시에 실행할때 사용합니다.

고루틴은 os 쓰레드를 이용하는 경량 쓰레드 이다.

컨텍스트 스위칭 : 쓰레드 전환에는 비용이 발생한다. 이것을 컨텍스트 스위칭이라고 한다.

보통 코어 갯수의 두배이상 스레드를 만들면 스위칭 비용이 많이 발생한다고 합니다.

만약 쓰레드 갯수와 코어 갯수가 같다명 어떻게 될가?

CPU 코어마다 OS 쓰레드를 하나만 할당해서 사용하기 때문에 컨텍스트 스위칭 비용이 발생하지 않기 때문에 성능이 좋다.

메인 함수도 고루틴 - 메인 고루틴이라고 부른다.

새로운 고루틴은 단순히 go 함수 로 만든다.

package main

import (
  "fmt"
  "time"
)

func PrintHangul() {
  hanguls := []rune{'', '', '', '', '', '', ''}
  for _, v := range hanguls {
    time.Sleep(300 * time.Millisecond)
    fmt.Printf("%c ", v)
  }
}

func PrintNumbers() {
  for i := 1; i <= 5; i++ {
    time.Sleep(400 * time.Millisecond)
    fmt.Printf("%d ", i)
  }
}

func main() {
  go PrintHangul()
  go PrintNumbers()

  time.Sleep(3 * time.Second)
}

메인 함수가 종료되면 아무리 많은 고루틴이 생성되어 잇더라도 모두 즉시 종료되고 프로그램이 종료됩니다.

서브 고루팅이 종료될 때까지 기다리기

sync 패키지의 WaitGroup를 사용하면됩니다.

쓰레드 풀처럼 동작하는듯. 여러개의 코어를 같이 쓸수가 잇게 되겟음 os 쓰레드니까.

코어가 2개고 고루틴이 3개면 3번째 고루틴은 대기한다. 고루틴이 하나가 끝나면 거기에 3번째에 넣어준다.

대기하는게 많아지면?? 보통 대기를 많이한다.

시스템 콜 호출시

시스템 콜이란 운영체제가 지원하는 서비스를 호출할때는 말합니다.

대표적으로 네트워크 / 파일 읽고 쓰기 등이 있습니다.

이때 대기상태로 들어간다. 그때 대기중인 고루틴과 교체가 된다.

아무리 많은 고루틴을 생성해도 OS 단에서 컨텍스트 스위칭 비용이 발생하지 않는다.

사실 고루틴이 교체되는것도 컨텍스트 스위칭이다. 이때 사용되는 컨텍스트가 os 컨텍스트 보다 스택이 작다.

동시성 프로그래밍 주의점

동일한 메모리 자원을 여러 고루틴에서 접근할때 동시성 문제가 발생한다.

뮤텍스 (상호배제)를 이용한 동시성 문제 해결

락을 걸어서 메모리 자원을 하나의 고루틴에서만 접근하게 해야한다.

defer를 사용

깃발을 꽂은 놈이 왕..

crtl+r로 프로그램 강제 종료

뮤텍스의 문제점

  • 동시성 프로그링으로 인상 성능 향상을 얻을수 없다. 심지어 과도한 락킹으로 성능이 하락되기도 한다.

  • 고루틴을 완전히 멈추게 만드는 데드락 문제 발생 (처음에는 잘 안보임..데드락..)

  • 데드락을 주의합시다.

뮤텍스 결론

  • 멀티코어 컴퓨터에서는 여러 고루틴을 사용하면 성능을 향상시킬수 있습니다.

  • 하지만 같은 메모리를 여러 고루팅ㅇ이 접근하면 프로그램이 꼬일수 있습니다.

  • 뮤텍스를 이용하면 동시에 고루틴 하나만 접근하도록 조정해 꼬이는 문제를 막을 수 있다.

  • 그러나 뮤텍스를 잘못 사용하면 성능향상도 데드락이라는 심각한 문제가 생길수 있습니다.

뮤텍스는 매우 조심히 사용해야한다. 그럼 아에 사용하지 말가? 그건 아니라고함. 가장 심플하게 사용할수 잇음...대신 조심하여...

뮤텍스를 쓰지 않아야 할까요? 뮤텍스가 고이지 않도록 좁은 범위에서 데드락에 걸리지 않는지 철저히 확인해서 사용하면 여전히 유용하고 손쉬운 방법입니다.

또다른 자원 관리 기법 (뮤텍스를 사용하지 않고)

  • 영역을 나누는 방법 - 서로 메모리를 따로 관리하면됨.

  • 역할을 나누는 방법 - 채널

Last updated