golang goroutine 介绍

  1. Goroutine 是用户态本身实现的线程,调度方式遇到IO/阻塞点方式就会让出cpu时间(其实也看编译器的实现,若是TA在代码里面插入一些yield,也是能够的。 反正如今不是抢占式的。)java

  2. 不能设置goroutine ID, 也拿不到(能够调用C API或者本身修改源码暴漏出来,实际上修改起来挺简单的,由于Go的源码写的很是简洁优雅)node

  3. goroutine的栈会自动扩容(初始stack很小,2KB,这也是go程序内存占用很小的缘由) 4.相对java,多线程调试工具链有待完善,不过咱们目前也没有发现须要这种调试的地方,实在须要时经过profile工具和简单的日志就能够( 目前有一些第三方的工具,不过由于并不须要,咱们也没有使用过)golang

  4. 开销很是小,同时运行几百万个一点问题都没有多线程

  5. go func(..) {} ()并发

  6. golang的最大特色就是这个goroutine很是简单方便,实现功能,都只要按照人类最直接的思惟模式写就好(反正能够开大量的goroutine),不像回调的方式那么碎片化(nodejs),也远远不像NIO那么复杂(netty).一句话:能够用最简单的方式写出来很是高性能的并发函数

package main

import (
    "log"
    "sync"
    "sync/atomic"
    "time"
)

var total int32 = 0

func main() {
    // 控制子线程的任务进行,等同于Map/Reduce处理
    wg := &sync.WaitGroup{}
    // 统计运行时间
    ts := time.Now()
    // 启动100万个线程,每一个线程执行100次加1的任务,这里使用了锁,防止脏数据
    for i := 0; i < 1000000; i++ {
        // go标记的函数,自动在一个 新的线程中去执行
        go func() {
            // 控制器的执行任务+1
            wg.Add(1)
            // 子线程结束时,控制器的任务执行完成
            defer wg.Done()
            for i := 0; i < 100; i++ {
                atomic.AddInt32(&total, 1)
            }
        }()
    }

    // 这里主线程休眠一小短期,防止子线程的任务控制wg.Add(1)尚未触发,主线程就执行完毕
    time.Sleep(1 * time.Millisecond)

    // 等待子线程的任务完成
    wg.Wait()

    // 输出最终运行时间
    log.Printf("启动100万个线程并执行计算任务完成,总计耗时:%v(毫秒)\n", time.Now().Sub(ts).Nanoseconds()/1000000)

    // 输出最终结果
    log.Println("最终计算结果为", total)
}
相关文章
相关标签/搜索