zoukankan      html  css  js  c++  java
  • 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 对协程原生支持

     

  • 相关阅读:
    XP显示桌面
    批量改名
    poj 3126 BFS
    poj 3278 BFS
    poj 1426 BFS
    准备打酱油…
    POJ 2243 BFS 和 简单的调试方法学习
    K
    EXCEL fundamentals
    poj 1011 DFS+剪枝
  • 原文地址:https://www.cnblogs.com/ycx95/p/9367128.html
Copyright © 2011-2022 走看看