golang协程

一、进程和线程

  1. 进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位
  2. 线程是进程的一个执行实例,是程序执行的最小单元,它是比进程更小的能独立运行的基本单位
  3. 一个进程可以创建和销毁多个线程,同一个进程中的多个线程可以并发执行
  4. 一个程序至少有一个进程,一个进程至少有一个线程

二、并发和并行

  1. 多线程程序在单核上运行,就是并发
  2. 多线程程序在多核上运行,就是并行

并发 :在一个cpu中,比如10个线程,每个线程执行10毫秒(进行轮询操作),从人的角度看,好像10个线程都在运行,但从微观上看,某一时间点看,其实只有一个线程在执行,这就是并发。
并行 :在多个cpu中(如10个),比如10个线程,每个线程执行10毫秒(各自在不同cpu上执行),从人的角度看,10个线程都在运行,但从微观上看,某一时间点看,也同时10个线程在执行,这就是并行。

三、go协程和主线程

go主线程是一个物理线程,直接作用在CPU上,是重量级的,非常耗cpu资源,一个go线程上可以起多个协程。
协程是主线程开启的,轻量级的线程,逻辑态的,对资源消耗小
go协程特点:

  1. 有独立的栈空间
  2. 共享程序的堆空间
  3. 调度由用户控制
  4. 协程是轻量级的线程

四、channel(管道)

  1. channel本质是一个数据结构-队列
  2. 数据是先进先出
  3. 线程安全,多goroutine访问时,不需要加锁,就是说channel本身是线程安全的
  4. channel是由类型的,一个string的channel只能存放string类型的数据
  5. 遍历时,如果channel没有关闭,则会出现deadlock错误,

如果channel已经关闭,则会正常遍历数据,遍历完毕后,就会退出遍历

细节:
管道可声明为只读或只写

var cha1 chan int // 可读可写
var cha2 chan<- int // 只写
var cha2 <-chan int // 只读

使用select可以解决从管道取数据的阻塞问题

// 实际开发中,不好确定什么时候关闭该管道
// 可用select解决
for {
    select {
        // 如果管道一直没关闭,不会一直阻塞而deadlock
        // 会自动到下一个case匹配
        case v := <-intChan:
            fmt.Printf("读取数据")
        case v := <-stringChan:
            fmt.Printf("读取数据")
        default:
            fmt.Printf("都取不到")
    }
}

goroutine中使用recover,解决协程中出现的panic,导致程序崩溃

你可能感兴趣的:(单元测试,goroutine)