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
}
}
}
网友评论