美文网首页
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