Go: process synchronization

发布时间 2023-04-24 19:28:59作者: ascertain

 

package main

import (
    "fmt"
    "math"
    "runtime"
    "strconv"
    "strings"
    "time"
)

func producer(intChan chan int) {
    for b := 1000; b <= 1099; b++ {
        intChan <- b
    }
    close(intChan)
}
func consumer(intChan chan int, primeChan chan int, exitChan chan bool) {
    var b, ok, flag = 0, true, true
    var lastNumber int
    for {
        lastNumber = b
        b, ok = <-intChan
        if !ok {
            exitChan <- true
            break
        }
        flag = true
        for v := 2; v < int(math.Sqrt(float64(b)))+1; v++ {
            time.Sleep(time.Millisecond * 30)
            if b%v == 0 {
                flag = false
                break
            }
        }
        if flag {
            primeChan <- b
        }
    }
    fmt.Printf("Goroutine(%03v) exit, last number: %v\n", GetGoroutineID(), lastNumber)
}
func main() {
    intChan := make(chan int, 100)
    primeChan := make(chan int, 2000)
    exitChan := make(chan bool, 4)
    go producer(intChan)
    for i := 0; i < cap(exitChan); i++ {
        go consumer(intChan, primeChan, exitChan)
    }

    go func() {
        for i := 0; i < cap(exitChan); i++ {
            <-exitChan
        }
        close(exitChan)
        close(primeChan)
    }()
    for {
        v, ok := <-primeChan
        if !ok {
            break
        }
        fmt.Printf("Prime: %v\n", v)
    }
    fmt.Printf("main Goroutine(%v) exit", GetGoroutineID())
}

func GetGoroutineID() int {
    var buf = make([]byte, 128)
    b := runtime.Stack(buf, false)
    idField := strings.Fields(strings.TrimPrefix(string(buf[:b]), "goroutine "))[0]
    id, err := strconv.Atoi(idField)
    if err != nil {
        panic(fmt.Sprintf("cannot get goroutine id: %v", err))
    }
    return id
}