go并发

go并发

2021年3月16日
18:27

goroutine:

Go语言在语言层面天生支持并发


串行:先洗完衣服再做饭,或者先做完饭再洗衣服。
并发:一会洗衣一会做饭。
并行:把洗衣盆拿到灶边,一只手做饭另一只手洗衣。

• 传统的多线程模型中创建一个新的线程代价高昂8M。
• Go语言中,每一个并发的执行单元叫作一个goroutine(协程)。类比轻量级的线程2kb 


Go语言中的操作系统线程和goroutine的关系:
1. 一个操作系统线程对应用户态多个goroutine。
2. go程序可以同时使用多个操作系统线程。(Go1.5版本之前,默认使用的是单核心执行。Go1.5版本之后,默认使用全部的CPU逻辑核心数。)
3. goroutine和OS线程是多对多的关系,即m:n。


使用goroutine:
在调用的函数(普通函数和匿名函数)前面加上一个go关键字

串行:

func hello() {
	fmt.Println("Hello Goroutine!")
} 
func main() { 
	hello() 
     fmt.Println("main goroutine done!") }

  

利用goroutine并行或并发:

func main() { 
    go hello() // 启动另外一个goroutine去执行hello函数
    fmt.Println("main goroutine done!") 
}

  

多个goroutine的同步:
1.time.Sleep()指定程序等待时间。不建议
2.sync.WaitGroup

var wg sync.WaitGroup
func hello(i int) { 
     defer wg.Done() // goroutine结束就登记-1
     fmt.Println("Hello Goroutine!", i)
} 
func main() {
     for i := 0; i < 10; i++ { 
         wg.Add(1) // 启动一个goroutine就登记+1 
         go hello(i) 
     }          
     wg.Wait() // 等待所有登记的goroutine都结束
}            

  


(每次打印的数字的顺序都不一致,因为这里10个goroutine是并发执行的)

 

GOMAXPROCS:
Go运行时的调度器使用GOMAXPROCS参数来确定需要使用多少个OS线程来同时执行Go代码。默认值是机器上的CPU核心数。例如在一个8核心的机器上,调度器会把Go代码同时调度到8个OS线程上(GOMAXPROCS是m:n调度中的n)。

Go语言中可以通过runtime.GOMAXPROCS()函数设置当前程序并发时占用的CPU逻辑核心数。



channel:
函数与函数间需要交换数据才能体现并发执行函数的意义
Go 语言中的通道(channel)是一种特殊的类型。通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型。

创建 通道是引用类型,通道类型的空值是nil ,make()中第二个参数是缓冲区大小
ch := make(chan int,10)

发送
ch <- 10 // 把10发送到ch中

接受
x := <- ch // 从ch中接收值并赋值给变量x <-ch // 从ch中接收值,忽略结果

关闭(通道是可以被垃圾回收机制回收)
close(ch)


· 对于关闭后的通道: 进行发送操作——panic异常
进行接收操作——正常接受之前已发送的数据

 

package main
import "fmt"
func main() {
    // var ch1 chan int
    // ch1=make(chan int,1)
    //ch1 := make(chan int) //无缓冲区通道(同步通道),必须当场立即传送值
    ch1 := make(chan int, 1)
    ch1 <- 10
    x := <-ch1
    fmt.Println(x)
    close(ch1)
    // len(ch1) 数量
    // cap(ch1) 容量
}

  


不带缓存的Channels:
• 无缓存Channels的发送操作将导致发送者goroutine阻塞,直到另一个goroutine在相同的Channels上执行接收操作。
• 如果接收操作先发生,那么接收者goroutine也将阻塞,直到有另一个goroutine在相同的Channels上执行发送操作。
• 当发送的值通过Channels成功传输之后,两个goroutine可以继续执行后面的语句。

 

单向通道:
限制通道在函数中只能发送或只能接收

只能发送
func counter(out chan<- int){}

只能接收
func printer(in <-chan int){}

 

posted @ 2021-04-20 23:25  秋月桐  阅读(106)  评论(0编辑  收藏  举报