go Getting 7 - goroutine

Finally came to go where the most powerful language support for concurrency level, which is a mechanism similar to coroutines, gorutine is a very lightweight to achieve, under normal circumstances, a single process can achieve ten million concurrent tasks. To carry out his basic concepts:

1. Note the concurrent parallel with the difference between:

  • Concurrency (concurrency), also known as co-feasibility refers to the ability to handle multiple simultaneous sexual activity, not necessarily the same moment between concurrent events.
  • Parallel (parallelism) refers to two concurrent events occurring simultaneously, meaning having concurrent, parallel and concurrent not necessarily

For example, the image is concurrency is zippered lane, is three lanes merge into a single lane intersection, the lane a car, it is incorporated into the turn lane, while the parallel is a three-lane, want to travel, you are free, after all RMB players.

Want more cattle efficiency, it needs high with recommended Apple trash, 28 nuclear, 30 + w soft sister currency, but in general, we encountered many cases are io operation, not so much calculation, so go the concurrent really low with a computer can also be efficient, which is go charm of it, under normal circumstances, go after the default process started a thread system to serve goroutine, but if you are RMB players, can be used to modify runtime.GOMAXPROCS so schedule multiple threads Used multicore parallelism.

Between 2.goroutine memory is not shared, but in order to enable communication between goroutine, you can use the channel, to achieve the "shared memory communication"

3.gorutine order of execution is not certain, and the introduction of the current process, not wait for the end of those gorutine you played,

This is simply played 10 gorutine, terminal print is not necessarily the result, with the computer about the status, simply print column three cases, my computer more garbage, is MacAir, saving money exchange trash

func tell(i int){
    fmt.Println("i am ", i)
}

func main(){
    fmt.Println("start")
    for i := 0; i < 10; i++{
        go tell(i)
    }
    fmt.Println("end")
}
1:
start
i am  1
i am  0
end
i am  2
2:
start
end
i am  5
i am  9
3:
start
end

Then there is a question, we want all of gorutine finished, how to do at the end of the program, there are several ways

You can use sync package WaitGroup, it can been waiting all groutine is finished, before the main course would have been blocked, ADD inform adds several gorutine, Done is to tell a gorutine end, equivalent to Add (-1) ,

Wait will block until there is empty

func tell(i int) {
    fmt.Println("i am ", i)
}

func main() {
    var wg sync.WaitGroup
    fmt.Println("start")

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            tell(i)
        }(i)
    }
    wg.Wait()
    fmt.Println("end")
}
//start
//i am  4
//i am  5
//i am  9
//i am  7
//i am  8
//i am  6
//i am  2
//i am  1
//i am  0
//i am  3
//end

In addition to the end of the current gorutine, you can use runtime.Goexit (), this will launch direct current gorutine, the scheduler will ensure that all registered defer executes, not the rest of execution

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        defer println("A.defer") // 执行
        func() {
            defer println("B.defer") // 执行
            runtime.Goexit()
            defer println("B.after defer")
            println("B")
        }()
        println("A")
    }()
    wg.Wait()
}

goroutine have too much effect you, for example you want to send a message, e-mail, text messaging, etc., directly from a gorutine, then returned and efficient.

The following Laijiangjiang ancillary channel

channnel default synchronous mode, sending and receiving pair, otherwise it will be blocked until the other is ready, the producer is the consumer model, enabled by default on a buffer chan, so when entered, stored data, if is not removed, it will choke means so close (msg) waits for a deposit, taken after the execution, and therefore it can be understood, the buffer is full, then the transmission will be blocked, if the buffer is empty, will be accepted clog

func main() {
msg := make(chan int)
flag := make(chan bool)
go func(){
fmt.Println("开始接受啦")
for i := range msg{
fmt.Println(i)
}
flag <- true
}()

for i := 0; i < 10; i++{
msg <- i
}
close(msg)
fmt.Println("关闭msg通道")
fmt.Println(<-flag)
}
}
//

It began to accept
0
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
closed channel msg
true

For example, I open the channel buffer is large, then the stored data will not be blocked, will be executed directly, then why did not the main program directly off of it, it is because the flag of this channel is blocked, he will wait until gorutine entered, save the data can only be taken out if there is no flag this channel, the program will launch direct, print results will look gorutine not played it.

func main() {
    msg := make(chan int, 10)
    flag := make(chan bool)
    go func() {
        fmt.Println("开始接受啦")
        for i := range msg {
            fmt.Println(i)
        }
        flag <- true
    }()

    for i := 0; i < 10; i++ {
        msg <- i
    }
    close(msg)
    fmt.Println("关闭msg通道")
    fmt.Println ( <- In Flag) 
} 
//
 close the passage msg 
start accepting it 
0 
. 1 
2 
. 3 
. 4 
. 5 
. 6 
. 7 
. 8 
. 9 
to true

If the data is sent to the channel closed, an error is reported, accompany panic capture, if the channel is closed twice, will be given

main FUNC () { 
    MSG1: = the make (Chan int ) 
    Close (MSG1) 
    // Close (MSG1)   // off twice, panic: Close Channel of Closed 
    fmt.Println (<- MSG1) // off value extracted is null, int null 0
     // MSG1 <- 2            // panic: Send ON closed channel 
    I, OK: = <-msg1 // can check whether the channel is off 
    iF OK { 
        fmt.Println (I) 
    } the else { 
        fmt.Println ( " MSG1 Closed " ) // MSG1 Closed 
    } 
}

Unidirectional channel, the channel can be set to accept only or send only, send to only transmitted, if data is taken from the inside, this error will need to specify the buffer to avoid an error, and vice versa, e.g.

func main() {
     m := make(chan int, 1)
    var send chan <- int = m
    var recv <-chan int =m
    send <- 1
    //<- send  // invalid operation: <-send (receive from send-only type chan<- int)
    //recv <- 1  // invalid operation: recv <- 1 (send to receive-only type <-chan int)
    println(<- recv) // 1
}

 select channel may be provided in conjunction with a timeout

main FUNC () { 
    W: = the make (Chan BOOL ) 
    C: = the make (Chan int , 2 ) 
    Go FUNC () { 
        SELECT { // If the two do not meet case, waits until meet 
        case V: = <- C: 
            fmt.Println (V) 
        Case <-time.After (time.Second * . 3 ): 
            fmt.Println ( " . timeout " ) 
        } 
        W <- to true 
    } ()
     <-w // blocked, waiting for the end of the program 
}

 

Guess you like

Origin www.cnblogs.com/yangshixiong/p/12134650.html