go并发编程

jincheng828 · · 1295 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

GO 并发编程

协程(进程 线程)

  1. 进程是“程序执行的一个实例” ,担当分配系统资源的实体。进程创建必须分配一个完整的独立地址空间。进程切换只发生在内核态。
  2. 线程:线程是进程的一个执行流,独立执行它自己的程序代码。
  3. 协程:协程不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用。在语言级别可以创建并发协程,然后编写代码去进行管理。go将这一步承包下来,使协程并发运行成本更低。
func main() {
    http.HandleFunc("/next", handler)
    // func这个函数会是以协程的方式运行。这样就可以提供程序的并发处理能力
    go func() {
        for i := 0; ; i++ {
            nextID <- i
        }
    }()
    http.ListenAndServe("localhost:8080", nil)
}

goruntime

参考goruntime详解,操作系统对cpu有自己的scheduler方案,如任务A在执行完后,选择哪个任务来执行,使得某个因素(如进程总执行时间,或者磁盘寻道时间等)最小,达到最优的服务。
Go有自己的scheduler,语言级别实现了并发。

每一个Go程序都附带一个runtime,runtime负责与底层操作系统交互,也都会有scheduler对goruntines进行调度。在scheduler中有三个非常重要的概念:P,M,G。
详情后续再写。

# Goroutine scheduler
# The scheduler's job is to distribute ready-to-run goroutines over worker threads.
#
# The main concepts are:
# G - goroutine.
# M - worker thread, or machine.
# P - processor, a resource that is required to execute Go code.
#     M must have an associated P to execute Go code, however it can be
#     blocked or in a syscall w/o an associated P.
#
# Design doc at https://golang.org/s/go11sched.

runtime包与goroutime

尽管 Go 编译器产生的是本地可执行代码,这些代码仍旧运行在 Go 的 runtime(这部分的代码可以在 runtime 包中找到)当中。这个 runtime 类似 Java 和 .NET 语言所用到的虚拟机,它负责管理包括内存分配、垃圾回收(第 10.8 节)、栈处理、goroutine、channel、切片(slice)、map 和反射(reflection)等等。

  • Gosched:让当前线程让出 cpu 以让其它线程运行,它不会挂起当前线程,因此当前线程未来会继续执行
  • NumCPU:返回当前系统的 CPU 核数量
  • GOMAXPROCS:设置最大的可同时使用的 CPU 核数
  • Goexit:退出当前 goroutine(但是defer语句会照常执行)
  • NumGoroutine:返回正在执行和排队的任务总数
  • GOOS:目标操作系统

NumCPU

package main
import (
    "fmt"
    "runtime"
)
func main() {
    fmt.Println("cpus:", runtime.NumCPU())
    fmt.Println("goroot:", runtime.GOROOT())
    fmt.Println("archive:", runtime.GOOS)
    // 4
    // /usr/local/golang
    // linux
}

GOMAXPROCS

package main

import (
    "fmt"
    "runtime"
)

func init() {
    runtime.GOMAXPROCS(1)
}

func main() {
    // 任务逻辑...
}

Golang 默认所有任务都运行在一个 cpu 核里,如果要在 goroutine 中使用多核,可以使用 runtime.GOMAXPROCS 函数修改,当参数小于 1 时使用默认值。

Gosched

这个函数的作用是让当前 goroutine 让出 CPU,当一个 goroutine 发生阻塞,Go 会自动地把与该 goroutine 处于同一系统线程的其他 goroutine 转移到另一个系统线程上去,以使这些 goroutine 不阻塞。

package main

import (
    "fmt"
    "runtime"
)

func init() {
    runtime.GOMAXPROCS(1)  # 使用单核
}

func main() {
    exit := make(chan int)
    go func() {
        defer close(exit)
        go func() {
            fmt.Println("b")
        }()
    }()

    for i := 0; i < 4; i++ {
        fmt.Println("a:", i)

        if i == 1 {
            runtime.Gosched()  #切换任务
        }
    }
    <-exit
}
# 运行结果
# a: 0
# a: 1
# b: 
# a:2
# a: 3

channel

channel是Go语言在语言级别提供的goroutine间的通信方式。我们可以使用channel在两个或 多个goroutine之间传递消息。
channel 会某种情况下出现阻塞,通过控制channel的阻塞来管理协程的并发与流程控制。


有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:jincheng828

查看原文:go并发编程

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1295 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传