美文网首页
go goroutine和channel的一个小demo

go goroutine和channel的一个小demo

作者: 嘉磊 | 来源:发表于2019-02-02 16:27 被阅读0次

写入文件

import (
    "fmt"
    "os"
    "strconv"
    "time"
)
func writeLog(i int, ch chan int) {
    file, err := os.OpenFile("config.txt", os.O_RDWR|os.O_APPEND, 0776)
    defer file.Close()
    if err != nil {
        panic(err)
    }
    file.WriteString("写入文件--" + strconv.Itoa(i) + "\n")
    ch <- i
}
func main() {
    fmt.Println("开始------")
    start := time.Now().UnixNano()

    ch := make(chan int, 5)
    for i := 1; i <= 5; i++ {
        go writeLog(i, ch)
    }
    <- ch
    end := time.Now().UnixNano()
    fmt.Println("结束------", (end-start)/1e6)
}

循环5次去写入文件。这种写法会有一个问题,当执行的时候,文件中的内容理论上来讲应该是

写入文件--5
写入文件--2
写入文件--1
写入文件--4
写入文件--3

但实际情况是,每次写的数量不固定(这可能是因为主线程执行完成,但是开启的goroutine还没跑完)
所以,修改下main,使用range遍历通道消息

func main() {
    fmt.Println("开始------")
    start := time.Now().UnixNano()

    ch := make(chan int)
    for i := 1; i <= 5; i++ {
        go writeLog(i, ch)
    }
    for s := range ch {
        fmt.Println(<-ch)
    }
    end := time.Now().UnixNano()
    fmt.Println("结束------", (end-start)/1e6)
}

此时,写文件的操作不会"丢失"了,但是程序会报错:fatal error: all goroutines are asleep - deadlock!
就是说,死锁了!因为range在通道不关闭的时候自己也不会停止读取,但是这个时候通道并没有内容可以给他读取了,所以就会阻塞当前goroutines,其结果就是死锁。
现在再修改main,使用缓冲通道

func main() {
    fmt.Println("开始------")
    start := time.Now().UnixNano()

    ch := make(chan int, 5)
    for i := 1; i <= 5; i++ {
        go writeLog(i, ch)
    }
    for j := 0; j < 5; j++ {
        fmt.Println(<-ch)
    }
    end := time.Now().UnixNano()
    fmt.Println("结束------", (end-start)/1e6)
}

好了,消停了,写入数量正常了,也不死锁了。

相关文章

网友评论

      本文标题:go goroutine和channel的一个小demo

      本文链接:https://www.haomeiwen.com/subject/dkissqtx.html