Go goroutine

并发性Concurrency

并发概念

Go是并发语言,而非并行语言。并发性是同时处理许多事情的能力。并行性parallelism指可以同时做很多事情。

Go中使用Goroutines来实现并发concurently。Goroutines是与其他函数或方法同时运行的函数或方法。

goroutines 

Goroutines被认为是轻量级的线程,与线程相比,创建Goroutines成本很小,故Go应用程序可以并发执行数千个Goroutines。

在线程上优势

  • 与线程相比,Goroutines非常便宜,只是堆栈大小的几个kb,堆栈可根据应用程序的需要增长和收缩。而线程情况下,堆栈大小必须指定并且是固定的。
  • Goroutines被多路复用到较少的OS线程,一个程序中可能只有1个线程与数千个Goroutines,若线程中任何Goroutine都表示等待用户输入,则会创建另一个OS线程,剩下的Goroutines被转移到新的OS线程。所有这些都由运行时处理,程序员从这些复杂细节中抽象出来,得到一个与并发工作相关的干净的API。
  • 使用Goroutines访问共享内存时,通过设计的通道可以防止竞态条件发生。通道可以被认为时Goroutines通信的管道。

Go语言协程

定义

不需要在定义时区分是否是异步函数(这点是针对Python3.5引入的async def定义时说明自己是一个协程)

调度器在合适的点进行切换(非抢占式的,但切换点也不是任意的点,传统是需要显示写出来,goroutine不需要)

可能切换的点:I/O,select  ; channel ;等待锁;函数调用(有时);runtime.Gosched()

注意:以上只是参考,不能保证切换,不能保证在其他地方不切换

使用-race来检测数据访问冲突

使用

任何函数或方法调用前面加上go就能送给调度器运行 ,运行一个新的Goroutine。

 例子:

例子1:

goroutine.go

输出是:Hello from goroutine 随机打印的值

查看系统究竟起了多少个线程?
top命令查看:CPU 占用率  #TH线程(根据系统核来)

 

Goroutine协程

子程序是协程的一个特例

协程特点:

轻量级”线程”

非抢占式多任务处理,由协程主动交出控制权 

编译器/解释器/虚拟机层面的多任务

多个协程可在一个或多个线程在工作

启动多个Goroutine

例子1

func numbers() {
    for i := 1; i <= 5; i++ {
        time.Sleep(250 * time.Millisecond)
        fmt.Printf("%d ", i)
    }
}
func alphabets() {
    for i := 'a'; i <= 'e'; i++ {
        time.Sleep(400 * time.Millisecond)
        fmt.Printf("%c ", i)
    }
}
func main() {
    go numbers()
    go alphabets()
    time.Sleep(3000 * time.Millisecond)
    fmt.Println("main terminated")
}
输出:1 a 2 3 b 4 c 5 d e main terminated

例子2

 

普通函数与协程对比:doWork做完了才把控制权交给main。

Goroutine规则:

  • 当新Goroutine开始时,Goroutine调用立即返回,且不等待Goroutine执行结束。
  • 当Goroutine调用,并且其任何返回值被忽略之后,go立即执行到下一行代码
  • main的Goroutine应该为其他的Goroutines执行,若main的Goroutine终止了,程序将被终止,其他Goroutine将不会运行。

例子:

func hello() {
    fmt.Println("Hello world goroutine")
}
func main() {
    go hello() //由于main进行Sleep,故go hello()有足够时间在main Goroutine终止之前执行
    time.Sleep(1 * time.Second)
    fmt.Println("main function")
}  //输出是:Hello world goroutine   main function   

其他语言对协程支持

Go语言原生支持

C++:通过Boost.Coroutine库支持

Java:不支持 (并不是完全不支持,有第三方的)

Python中:Python3.5以前使用yield关键字实现协程,Python3.5加入了async def 对协程原生支持

 

原文地址:https://www.cnblogs.com/ycx95/p/9367128.html