By duct (channel) synchronized

GO language has many ways to achieve synchronization, a mutex (sync.Mutex), channel communications and so on;
sum up the way Go in the channel today!

the communication channel comprises two modes: one is with unbuffered the channel, the other is the buffer of the channel;

1, no buffering

Each transmission channel in unbuffered operation, there will be paired with a corresponding receiving operation, sending and receiving operations often occur on two goroutine ( two operations are performed in the same goroutine deadlock-prone ), uncached send operation always occurs on the channel prior to receiving the operation;

First, synchronization is achieved by way of an unbuffered:

func main() {
    done := make(chan int)

    go func(){
        fmt.Println("hello world!")
        <-done
    }()

    done <- 1
}

The GO model specification language memory, for receiving channel buffer never carried out, this occurs before the completion of the transmission channel is performed. Thus complete background thread <- done after the reception operation, done main function <- possible to complete the operation transmitting (and thus exit the main, exit the program), but this time the printing has been completed.

Although the above code synchronization can be done, but the pipeline buffer size too sensitive, if the pipe buffer, then not be able to guarantee the main background thread exit normal printing .

Better approach is to change what receive and transmit direction, the buffer size so that the influence can be avoided by synchronized;

func main() {
    done := make(chan int, 1) // 带缓存的管道

    go func(){
        fmt.Println("hello world!")
        done <- 1
    }()

    <-done
}

2, a buffer manner

For Channel buffered, for the K-th Channel reception occurs before the completion of the K + C transmitting operation is completed , where C is the buffer size of the Channel. Although the pipeline is unbuffered, main thread receives a transmission start completion but not yet completed at the time the background thread, then the print job is completed.

Based on the pipeline with the cache, we can easily be extended to the N print thread. The following example is open 10 respectively print background thread:

func main() {
    done := make(chan int, 10) // 带 10 个缓存

    // 开N个后台打印线程
    for i := 0; i < cap(done); i++ {
        go func(){
            fmt.Println("hello world!")
            done <- 1
        }()
    }

    // 等待N个后台线程完成
    for i := 0; i < cap(done); i++ {
        <-done
    }
}

For this to wait after the completion of N threads synchronize the next there is a simple approach is to use sync.WaitGroup to wait for a set of events:

func main() {
    var wg sync.WaitGroup

    // 开N个后台打印线程
    for i := 0; i < 10; i++ {
        wg.Add(1)

        go func() {
            fmt.Println("hello world!")
            wg.Done()
        }()
    }

    // 等待N个后台线程完成
    wg.Wait()
}

Which wg.Add (1) increase the number of waiting for an event , you must ensure the implementation (if placed in a background thread execution is not guaranteed to be properly executed) before starting a background thread. When the background thread to complete the print job, calling wg.Done () represents a complete event . The main function of wg.Wait () is waiting for the completion of all events .

Personal github account: https://github.com/SpecialAll

Published 49 original articles · won praise 11 · views 20000 +

Guess you like

Origin blog.csdn.net/qq_41999455/article/details/103770588