美文网首页
Goroutine快速入门

Goroutine快速入门

作者: Jaeyok | 来源:发表于2020-11-26 16:33 被阅读0次

    Go协程四大特点
    有独立的栈空间
    共享程序堆空间
    调度由用户控制
    协程是轻量级的线程

    主线程和协程同时执行

    package main
    
    import (
        "fmt"
        "time"
    )
    
    
    func test(){
        for i:=0; i<10;i++{
            fmt.Println("hello World")
            time.Sleep(time.Second)
        }
    }
    
    
    func main() {
    
    
        go test() //开启一个协程
    
        for i:=0; i<10;i++{
            fmt.Println("main hello World")
            time.Sleep(time.Second)
        }
    
    }
    

    如果主线程退出了,协程没有执行完毕也会退出。
    协程有可能自己退出在主线程没结束之前。

    设置CPU运行最大个数

         cpunum := runtime.NumCPU()
         fmt.Println(cpunum)
         runtime.GOMAXPROCS(cpunum-1) //设置运行的CPU数目
         
    

    全局变量加锁解决并发资源竞争问题

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    var (
        myMap = make(map[int]int, 10)
        lock sync.Mutex // lock是一个全局的互斥锁 Mutex互斥
    
    )
    
    func test(n int ){
       res:=1
       for i:=1; i<=n; i++{
        res *= i
       }
    
       lock.Lock()
       myMap[n] = res
       lock.Unlock()
    }
    
    
    func main() {
    
    for i:=1; i<=20; i++{
        go test(i)
    }
    
    time.Sleep(time.Second*5)
    
    lock.Lock()
    for k,v := range myMap {
        fmt.Printf("%d!= %v\n",k,v)
    }
    lock.Unlock()
    
    }
    

    管道快速入门

    使用管道channel解决并发资源竞争
    管道FIFO, 本质上是一个队列数据结构。线程安全,不需要加锁。管道是有类型的。

    channel必须初始化Make才能运行

    package main
    
    import "fmt"
    
    
    type Person struct {
        Name string
        Age int
    }
    
    func main() {
    
    var intChain chan int
    intChain =make(chan int, 3) //最多三个
    //放入数据
    intChain <-10
    num := 221
    intChain <- num
    //从管道取数据
    
    //t如果全部取出, 会报死锁。
    num2 := <-intChain
    num3 := <- intChain
    fmt.Println("字符串channel:",num2,num3,len(intChain)) //chan是一个地址
    
    //struct类型的管道
    var structChain chan Person
    
    structChain = make(chan Person, 10)
    
    p1 := Person{
        Age: 18,
        Name: "Tom",
    }
    
    structChain <-p1
    p2 := <- structChain
    fmt.Println("结构体channel为",len(structChain))
    fmt.Println(p2)
    
    //接口类型的管道
    var allchain chan interface{}
    allchain = make(chan interface{}, 10)
    allchain <- p1
    allchain <- 10
    allchain <- "jack"
    
    newperson := <-allchain
    fmt.Println(newperson) // newperson是接口类型不是结构体类型
    
    //使用类型断言 变成结构体类型,再取出名字
    
    fmt.Println("Person的Name:", newperson.(Person).Name)
    
    //channel的关闭 只读不可写
    close(allchain)
    //allchain <-"sds" //panic: send on closed channel
    
    num1 := <- allchain
    fmt.Println(num1)
    //channel的遍历 不能使用for循环
    
    intChain2 := make (chan  int, 100)
    for i:=0; i<100; i++{
        intChain2 <- i*2
    }
    close(intChain2) // 遍历之前必须关闭管道 否则死锁
    for v := range intChain2{
        fmt.Println("v=",v)
    }
    
    }
    
    package  main
    
    import (
    
        "fmt"
    )
    
    
    func writeData(intChain chan int){
        for i:=1; i<=50 ; i++{
            intChain <- i
            fmt.Println("write data",i)
        }
        close(intChain)
    }
    
    func readData(intChan chan int, exitChan chan bool ){
        for{
            v,ok := <-intChan
            if !ok{
                break
            }
            fmt.Println("读到数据:",v)
        }
        exitChan <- true
        close(exitChan)
    }
    
    
    
    func main(){
    
        var intChain = make(chan int, 50)
        var exitChain  = make (chan bool,1)
    
        go writeData(intChain)
        go readData(intChain,exitChain)
    
        for {
            v,ok := <-exitChain
            fmt.Println("exchain:", v)
            if !ok{
                fmt.Println("程序结束:", ok,v)
                break
            }
        }
    
    
    }
    

    相关文章

      网友评论

          本文标题:Goroutine快速入门

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