Go의 동시 및 채널

5163 단어 concurrencygochannels
본고는 귀하가 Golang에 관한 글을 읽고 최소한 기본 지식을 이해했다고 가정합니다.

개요:


Go 채널을 설명하기 전에 병발성이 무엇인지, 어떤 문제점이 있는지 살펴봐야 한다.
우리는 한 라인에서 순서대로 임무를 운행할 수 있다.그러나 그것은 어떤 문제를 해결하기에 적합하지 않다.따라서 우리는 여러 개의 라인을 사용하여 임무를 비동기적으로 운행할 수 있다.병발성은 병행성과 다르며 병행성에서 임무는 동시에 집행된다.병행 운행 임무는 하드웨어와 소프트웨어 수요의 혼합이다.그러나 병발성은 코드 디자인과 관련이 있다.

In computer science, concurrency is is the ability of different parts or units of a program, algorithm, or problem to be executed out-of-order or in partial order without affecting the final outcome.



동시에 몇 가지 문제가 발생할 수 있다.자원을 공유하는 것이 그 중의 하나다.공유 자원은 여러 라인에서 동시에 접근할 수 있다.따라서 이 자원에 접근하는 순서가 중요하다.한 라인이 공유 변수를 읽으려고 시도할 때, 다른 라인은 공유 변수의 값을 변경할 수 있습니다.이것은 불일치를 초래할 수 있다.

Go의 동시 솔루션


우리는 상호 배척 자물쇠, 신호량, 자물쇠 등을 사용하여 병발 문제를 해결할 수 있습니다. 기본적으로 한 라인이 공유 자원에 접근하려고 시도할 때, 다른 라인은 공유 자원에 접근할 수 없습니다. 이 라인이 잠길 때까지 공유 자원에 접근할 수 없습니다.

Go solves these problems in another way. It uses goroutines instead of threads and uses channels instead of accessing to shared state.


Goroutines:


기존 Java 응용 프로그램의 스레드는 JVM을 통해 OS 스레드에 직접 매핑됩니다.Go는 스레드 대신 goroutines를 사용합니다.goroutine는 소량의 운영체제 라인에 분배됩니다.그것들은 go가 실행될 때의 가상 공간에만 존재한다.Go에는 필요할 때 확장할 수 있는 세그먼트 스택이 있습니다.이것은 운영체제가 아닌 Go가 실행할 때 제어한다는 것을 의미한다.
  • Goroutines는 시동 시간과 같은 다른 장점도 있다.goroutine의 시동 속도가 라인보다 빠르다.
  • Goroutines의 스택 크기는 2KB에 불과합니다.Java 스레드의 스택 크기는 약 1MB입니다.
  • func goRoutineA(a <-chan int) {
        val := <-a
        fmt.Println("goRoutineA received the data", val)
    }
    func main() {
        ch := make(chan int)
        go goRoutineA(ch)
        time.Sleep(time.Second * 1)
    }
    
    그것을 호출할 때, 고 키워드를 볼 수 있습니다.그것은 함수를 비동기적으로 한다.자바에서, 우리는 하나의 라인을 만들고, 이 라인에서 리셋 방법을 호출해서 같은 일을 할 수 있다.

    goroutines는 어떻게 소통합니까?


    Goroutines는 유용합니다.그런데 어떻게 소통을 할까요?
    지난 장에서 우리는 자원을 공유하는 용어를 배웠다.GoOutine이 공유 리소스에 액세스했습니까?답안은 부정적이다.
    The philosophy behind the Go's concurrency is:

    Do not communicate by sharing the memory; share memory by communicating.


    사람들은 바둑에서 자원을 공유하는 것을 좋아하지 않고 경로로 고루틴스를 교류한다.

    Go 채널:


    바둑 채널은 파이프와 같다.한 고로틴은 데이터를 보내고, 다른 고로틴은 다른 쪽에서 데이터를 받는다.두 가지 유형의 채널을 버퍼 채널과 비버퍼 채널이라고 부른다.
    ch := make(chan string) //unbuffered channel 
    ch := make(chan string, 5) //buffered channel
    
    버퍼 채널에 지정된 용량이 있습니다.그러나 버퍼가 없는 채널은 여러 개의 데이터를 수용할 수 있는 능력을 갖추지 못한다.이것은 한 번에 하나의 데이터만 버퍼 채널을 통과할 수 있다는 것을 의미한다.

    hchan struct
    When we write make(chan int, 5)channel is created from the hchan struct, which has the following fields.


    type hchan struct {
        qcount   uint           // total data in the queue
        dataqsiz uint           // size of the circular queue
        buf      unsafe.Pointer // points to an array of dataqsiz elements
        elemsize uint16
        closed   uint32
        elemtype *_type // element type
        sendx    uint   // send index
        recvx    uint   // receive index
        recvq    waitq  // list of recv waiters
        sendq    waitq  // list of send waiters
    
        // lock protects all fields in hchan, as well as several
        // fields in sudogs blocked on this channel.
        //
        // Do not change another G's status while holding this lock
        // (in particular, do not ready a G), as this can deadlock
        // with stack shrinking.
        lock mutex
    }
    
    type waitq struct {
       first *sudog
       last  *sudog
    }
    
    채널 구조에서 만나는 몇 개의 필드에 대해 설명합니다.
    데이터qsize는 위 버퍼 크기, 즉 make(chan T, N), N입니다.
    elemsize는 단일 요소에 대응하는 채널 크기입니다.
    buf는 실제 데이터를 저장하는 순환 대기열입니다.(버퍼 채널에만 해당)
    closed는 현재 채널이 닫힌 상태인지 여부를 표시합니다.채널을 만들면 이 필드는 0으로 설정됩니다. 즉, 채널이 열립니다.close를 호출하여 1로 설정하면 채널이 닫힙니다.
    sendx와recvx는 고리형 버퍼의 상태 필드로 버퍼 백업 진열의 현재 인덱스를 가리키며 데이터를 보내고 수신할 수 있습니다.
    recvq와sendq 대기 대기열은 채널의 데이터를 읽거나 채널에서 데이터를 보내려고 시도할 때 막힌 goroutine를 저장하는 데 사용됩니다.
    전송과 수신은 서로 밀어냄 작업이어야 하기 때문에 모든 읽기와 쓰기 작업의 채널을 잠그십시오.

    sudog represent the goroutine. sudog struct:


    type sudog struct {
       g     *g             //goroutine
       elem  unsafe.Pointer // data element 
       ...
    }
    
    기본적으로 버퍼가 없는 채널에서 쓰기와 읽기가 막힙니다.하나의 고루틴이 데이터를 보낼 때, 다른 고루틴이 채널에서 데이터를 받을 때까지 차단됩니다.접수 부분도 마찬가지다.goroutine가 채널에서 데이터를 수신하려고 시도할 때, 데이터가 채널로 전송될 때까지 차단됩니다.버퍼 채널에도 마찬가지다.용량이 가득 차면 다른 goroutine가 채널에서 데이터를 가져올 때까지 발송자 goroutine가 차단됩니다.
    동시 발생을 처리할 때는 Go 응용 프로그램에서 Go 채널을 사용하는 것이 좋습니다.그러나 문제가 채널을 통해 해결되지 않으면 동기화 패키지를 통해 다른 해결 방안을 사용할 수 있습니다.이 패키지는 상호 배척체 등 저급 구성 요소를 제공한다.

    결론:


    나는 이 문장이 Goroutine와Channel의 기초 지식을 배우는 데 도움이 되기를 바란다.만약 당신이 어떤 생각이나 피드백을 가지고 있다면 아래의 토론 부분에 쓰십시오.

    좋은 웹페이지 즐겨찾기