go 并发知识总结

关键知识点:

基础知识:

线程与进程:进程是资源分配的最小单位,线程是独立运行的基本单位

并行与并发:同一个cpu上执行叫并发、多个cpu上执行叫并行

协程于线程:协程是栈私有,堆共享,调度自己控制。协程是轻量级的线程。(java中调度可以是jvm、抢占式等外界力量对其调度)

核心知识点:

goroutine:  官方定义的“线程池”,运行时候调度管理

内部的调度GMP(goroutine、Processor、Machine):Processor就是个队列,思路就是解耦,有了P的存在,就将g和m分开了,使得两者独立。本质上和线程池思路没啥区别

runtime包:

goSched让出cpu对标java中的sleep,cpu没有,资源应该还在手?

goExit就是协程退出,对标java的stop。一般来说不会粗鲁的停止对应的协程

goMaxProcs 最大的核心os数,对标线程池的最大核心线程数

channel:实现通过通信共享内存不是通过共享内存来实现通信。(简单理解为mq)

channel  := make(chan string, 10)

panic出现的情况:读取已经关闭的通道、关闭已经关闭的通道

select:类似switch,哪个通道读取成功,执行哪个

互斥:   sync.Mutex/RWMutex,  lock and unlock

              sync.waitGroup(n),  add, done, wait

              sync.once only run once

              sync.map  线程安全的map

atomic:主要是操作一些基础类型,进行一些原子操作

经典demo:

channel通道:

import (
    "fmt"
    "math/rand"
)

type Job struct {
    // id
    Id int
    // 需要计算的随机数
    RandNum int
}

type Result struct {
    // 这里必须传对象实例
    job *Job
    // 求和
    sum int
}

func main() {
    // 需要2个管道
    // 1.job管道
    jobChan := make(chan *Job, 128)
    // 2.结果管道
    resultChan := make(chan *Result, 128)
    // 3.创建工作池
    createPool(64, jobChan, resultChan)
    // 4.开个打印的协程
    go func(resultChan chan *Result) {
        // 遍历结果管道打印
        for result := range resultChan {
            fmt.Printf("job id:%v randnum:%v result:%d\n", result.job.Id,
                result.job.RandNum, result.sum)
        }
    }(resultChan)
    var id int
    // 循环创建job,输入到管道
    for {
        id++
        // 生成随机数
        r_num := rand.Int()
        job := &Job{
            Id:      id,
            RandNum: r_num,
        }
        jobChan <- job
    }
}

// 创建工作池
// 参数1:开几个协程
func createPool(num int, jobChan chan *Job, resultChan chan *Result) {
    // 根据开协程个数,去跑运行
    for i := 0; i < num; i++ {
        go func(jobChan chan *Job, resultChan chan *Result) {
            // 执行运算
            // 遍历job管道所有数据,进行相加
            for job := range jobChan {
                // 随机数接过来
                r_num := job.RandNum
                // 随机数每一位相加
                // 定义返回值
                var sum int
                for r_num != 0 {
                    tmp := r_num % 10
                    sum += tmp
                    r_num /= 10
                }
                // 想要的结果是Result
                r := &Result{
                    job: job,
                    sum: sum,
                }
                //运算结果扔到管道
                resultChan <- r
            }
        }(jobChan, resultChan)
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值