Go practical language reading notes (2): Concurrent

Foreword

  • Benpian notes on "Go practical language."
  • Benpian major record some notes, or where different versions of gopl did not mention the
  • This section is all about concurrency, more important, it took more effort

Complicated by

  • Parallel is to allow different code segments simultaneously on different physical processor (CPU) performs on
  • Parallel is doing many things at the same time
  • Concurrency is manage a lot of things, these things can only do half of it was suspended do something else

Thread (thread) and process (process)

  • When running an application, the operating system will launch a program for this process , this process includes a variety of application needs to use resources in operation and maintenance (including memory address space, file and device handles, threads , etc.), equivalent container
  • A thread is an execution space, which the operating system will be scheduled (this is the OS thread scheduler, a distinction goroutine scheduler) to run the code written in the function
  • Each process contains at least one thread , each process of the initial thread is called the main thread
  • Since the main thread space is the application of space itself, so the main thread termination, the application will be terminated
  • OS thread scheduler can schedule threads to a processor (CPU) running
  • The operating system of physical processor (CPU) scheduler thread and the thread run

goroutine Overview

  • Go language from concurrent synchronization model called CSP (Communicating Sequential Processes) paradigm (paradigm)
  • Go concurrent language refers to the ability to make a function independent of other functions to run
  • When you create a function goroutine, Go treats it as an independent unit of work
  • This unit is scheduled (by the goroutine scheduler implemented) to an available logical processor executing
  • goroutine scheduler can manage all goroutine be created and assigned execution time; the operating system can be a thread with language runtime logic processor binding, and logic processor running on goroutine

goroutine concurrency and parallelism

  • The operating system in the physical processor scheduling a thread to run, while the Go language program is running in a logical processor scheduling on goroutine run
  • Each logical processor are each bound to a single OS thread
  • In version 1.5, Go will be for each available language runtime physical processor (CPU) is assigned a logical processor ; prior version 1.5, by default the entire application allocates only one logical processor
  • If you create a goroutine and ready to run, this will be placed goroutine Go scheduler of global run queue , after which Go scheduler will this goroutine assigned to a logic processor, the logical processor to be placed in the corresponding local operating queue
  • Local run queue goroutine will have to wait to know the assigned logical processor execution

  • Logical processor is uniquely tied to the operating system thread
  • When you need to perform a blocking system calls, running goroutine thread and will goroutine from logic processor separation, the thread will continue to clog, wait for the system to return calls
  • At the same time, logical processors lose the thread to run, then Go scheduler creates a new thread , and the thread is bound to the logical processor
  • 之后,Go调度器会从本地运行队列里选择另一个goroutine来运行
  • 一旦被阻塞的系统调用返回,对应的goroutine会被放到本地运行队列,而之前的线程会保存好,以便后用

  • Go调度器对可以创建的逻辑处理器的数量没有限制,但Go语言运行时默认限制每个程序最多创建10000个线程
  • 可以通过runtime/debug包的SetMaxThreads方法来更改每个程序最多创建的线程数
  • 如果希望goroutine并行,必须使用多于一个逻辑处理器
  • 当有多个逻辑处理器时,Go调度器会将goroutine平等分配到每个逻辑处理器上,也就是让goroutine在不同的线程上运行
  • 不过要想真的实现并行的效果,用户需要让自己的程序运行在多个物理处理器(CPU)的机器上

概念小整理

  • 上述有关并发的概念都加粗处理了
  • 物理处理器,线程,进程,主线程,应用程序,操作系统线程调度器,Go调度器,逻辑处理器,全局运行队列,本地运行队列
  • 笔者的小结:
    1.当启动一个应用程序,操作系统会为其创建相应的进程
    2.进程拥有应用程序所需的各种资源,包括内存地址空间,线程
    3.每个进程至少有一个线程,每个进程的初始线程被称为主线程
    4.线程是一个执行空间,而主线程的空间就是应用程序的空间,因此主线程终止,应用程序也会终止
    5.操作系统线程调度器可以将线程调度到物理处理器(CPU)
    6.物理处理器(CPU)调度线程并运行
    7.对于Go语言1.5以上版本的程序(进程)而言,Go调度器默认会为每个可用物理处理器(CPU),分配一个逻辑处理器
    8.创建一个goroutine并运行,这个goroutine会被放在Go调度器全局运行队列
    9.Go调度器负责把这些队列中goroutine分配给一个逻辑处理器,并且将这个逻辑处理器绑定到唯一的操作系统线程
    10.逻辑处理器会将相应的goroutine放入本地运行队列
    11.本地运行队列中的goroutine会一直等待直到自己被分配到逻辑处理器执行
    12.当goroutine执行一个阻塞的系统调用,其对应线程会从逻辑处理器上分离,该线程被阻塞,等待系统调用的返回
    13.Go调度器会为失去线程的逻辑处理器创建一个新线程,并将新线程绑定到该逻辑处理器
    14.系统调用执行完成并返回,对应的goroutine会放回到本地运行队列,而之前的线程会被保存后,以便后用

goroutine

  • runtim包中的GOMAXPROCS(num)函数可以设置分配给Go调度器使用的逻辑处理器的数量
  • runtime包中的NumCPU()可以获取可以使用的物理处理器数量
  • sync包中WaitGroup类型,通过它的add方法可以计数,Done方法来减少计数,Wait方法来等待计数结束

竞争状态(race condition)

  • 定义:如果两个或多个goroutine在没有相互同步的情况下,访问某个共享的资源,并试图同时读和写这个资源,就处于相互竞争的状态
  • Go语言有一个工具可以在代码里检测竞争状态:go build -race
  • gopl-zh的翻译者翻译成了竞争条件,反而不好理解

锁住共享资源(竞争状态的处理方法)

  • sync/atomic包中原子函数
  • sync包中的互斥锁(gopl还提到了读写锁)
  • 通道方法:
    1. 无缓冲通道

    2. 有缓存通道

    3. 特别说明:当通道关闭后,goroutine依旧可以从通道接收数据,但是不能再向通道里发送数据

并发模式

runner

  • runner包用于展示如何使用通道来监视程序的执行时间,如果程序运行时间太长,也可以用runner包来终止运行
  • 笔者理解:使用Runner模式来执行一系列串行任务,可以设置运行的时间,还可以终止运行
  • corn作业 :crontab命令常见于Unix和类Unix的操作系统之中,用于设置周期性被执行的指令。该命令从标准输入设备读取指令,并将其存放于“crontab”文件中,以供之后读取和执行。该词来源于希腊语chronos(χρόνος),原意是时间。通常,crontab储存的指令被守护进程激活,crond常常在后台运行,每一分钟检查是否有预定的作业需要执行。这类作业一般称为cron jobs。

pool

  • pool包用于展示如何使用有缓冲的通道实现资源池,来管理可以在任意数量的goroutine之间共享及独立使用的资源
  • Go1.5版本并没有pool包,而1.6及以后版本中,实现标准库sync.Pool资源池,推荐使用

work

  • work包的目的是展示如何使用无缓冲的通道来创建一个goroutine池,这些goroutine执行并控制一组工作,让其并发执行

小结

  • 可以使用通道来控制程序的生命周期
  • 带default分之的select语句可以用来尝试向通道发送或者接收数据,而不会阻塞
  • 有缓冲的通道可以用来管理一组可复用的资源
  • 语言运行时会处理好通道的协作和同步
  • 使用无缓冲的通道来创建完成工作的goroutine池
  • 任何时间都可以用无缓冲的通道来让两个goroutine交换数据,在通道操作完成时一定保证对方接收到数据

Guess you like

Origin www.cnblogs.com/laiyuanjing/p/11291658.html