GO-并发技术

本文深入探讨Go语言的并发特性,包括CSP并发理论、多协程、管道通信和死锁问题。介绍了无缓存和有缓存的channel、同步调度策略,并提供了死锁的常见场景分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

并发技术1:CSP并发理论

异步async 
并行:多个任务并发执行

同步sync 
串行:多个任务依次执行

阻塞block 
某个并发任务由于拿不到资源没法干活,从而无所事事地干等

异步回调async callback 
A线程唤起B线程,令其干活 
同时给B一个回调函数 
命令B在干完活以后,执行这个回调函数 
这个回调函数会与A线程发生交互 
A不必阻塞等待B执行的结果,AB两个线程可以并发执行 
利弊

  • 效率高
  • 回调地狱CallbackHell,逻辑线不清晰

共享内存

  • 多个并发线程通过共享内存的方式交互数据
  • 线程安全问题:AB间共享的数据地址可能被C并发修改

同步锁/资源锁 
为了解决共享内存所导致的线程安全问题,共享的内存地址在特定时间段被特定线程锁定 
加锁期间,其它线程无法访问,带来低效率问题

死锁 
A锁住B的资源 
B锁住A要的资源 
AB同时阻塞 
案例:小两口的冷战

  • 女:锁住女人的尊严,得到男人的尊严后才释放
  • 男:锁住男人的尊严,得到女人的尊严后才释放

线程池

  • 背景:线程的开销大
  • 内存:保存上下文数据
  • CPU:线程调度

    为了避免无度创建线程(内存溢出OutOfMemory),在一个池中创建一堆线程,循环利用这些线程,用完了以后重置并丢回池中.

  • 利弊

    利:避免了无度创建线程,降低了OOM的风险
    弊:用不用都占去了一大块内存开销
    

线程并发的弊端 
开线程占内存 
啥也不干就拿走1M栈空间 
1024条线程就占用1G内存 
线程切换占CPU 
内存共享不安全 
加了锁效率又低下 
回调地狱导致开发难度高

堆栈 

  • 变量和对象的名称
  • 引用堆地址

  • 杂乱无章地堆放各种数据
  • 没有栈对其进行引用时,就由nil进行引用
  • 被nil引用的堆地中的内容随时可能被垃圾回收器回收

垃圾回收

  • 一块堆内存如果没有被栈引用,就会被0号栈(空nil)所引用
  • 一切被nil引用的对内存,会随时被垃圾回收器(GarbageCollector=GC)回收

CSP模型

  • CommunicatingSequentialProcess
  • 可通信的序列化进程
  • 并发的进程间通过管道进行通信

共享内存 VS 管道

  • 内存共享:通过内存共享通信
  • 管道:通过通信共享内存

管道

  • 最早由CSP模型提出
  • 以点对点管道代替内存共享实现并发进程间的数据交互
  • 相比内存共享数据交互的相率要高很多

协程

  • coroutine
  • coorperte
  • 协作
  • IO时让出CPU
  • routine
  • 事务
  • 微线程/纤程

并发技术2:多协程

创建Goroutine

import (
    "fmt"
    "time"
)

func newTask() {
    for {
        fmt.Println("劳资是子协程")
        time.Sleep(time.Second)
    }
}

func main() {

    //开一条协程,与主协程并发地执行newTask()
    go newTask()

    //主协程赖着不死,主协程如果死了,子协程也得陪着死
    for {
        fmt.Println("this is a main goroutine")
        time.Sleep(time.Second)
    }

}

出让协程资源 
通过runtime.Gosched()出让协程资源,让其他协程优先执行

package main

import (
    "fmt"
    "runtime"
)

func main() {

    go func() {
        for i := 0; i < 5; i++ {
            fmt.Println("go")
        }
    }()

    for i := 0; i < 2; i++ {
        //让出时间片,先让别的协程执行,它执行完,再回来执行此协程
        //(詹姆斯协程:先排档期,你们先上)
        runtime.Gosched()
        fmt.Println("hello")
    }

}

协程自杀

package main

import (
    "fmt"
    "runtime"
    "time"
)

func test() {
    //遗嘱:临终前说的话
    defer fmt.Println("这是test的遗嘱")
    //自杀,触发提前执行遗嘱,暴毙,后边的好日子不过了,调用它的协程也暴毙
    runtime.Goexit()
    //自杀了,后边的好日子不过了
    fmt.Println("生活承诺的很多美好事情...")
    //到这是test的正常退出
}

func wildMan()  {
    for i:=0;i<6;i++{
        fmt.Println("我是野人,我不喜欢约束,我讨厌制约的我的主协程")
        time.Sleep(time.Second)
    }
}

func main() {

    //一个会暴毙的协程
    go func() {
        fmt.Println("aaaaaaaaaaaaaa")
        //test中有协程自杀程序runti
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值