golang 并发

打印 上一主题 下一主题

主题 932|帖子 932|积分 2796

Golang 并发


  • 并行 指的是在同一时刻 有多条指令在多个CPU处理器上同时执行 2个任务2个窗口需要硬件支持
  • 并发是指在同一时刻 只能有一条指令 单多个进程指令快速轮换执行 2个队伍1个窗口 要求提升软件能力
Golang 并发优势


  • go 从底层就支持并发
  • 简化了并发程序的编写方法
Goroutine 是什么


  • 它是go 并发设计的核心
  • goroutine就是协程,它比线程更小,十几个goroutine 在底层可能就是五六个线程
  • go 语言内部实现了goroutine的内存共享,执行goroutine只需极少的栈内存(大概4-5KB)
创建goroutine


  • 只需要在语句前添加go 关键字即可
  1.     package main
  2.     import (
  3.     "fmt"
  4.     "time"
  5.     )
  6.     //测试协程
  7.     //循环打印内容
  8.     func newTask() {
  9.     i := 0
  10.     for {
  11.     i++
  12.     fmt.Printf("new goroutine\:i=%d\n", i)
  13.     time.Sleep(1 \* time.Second)
  14.     }
  15.     }
  16.     //main()相当于是主协程
  17.     func main() {
  18.     //启动子协程
  19.     go newTask()
  20.     i := 0
  21.     for {
  22.     i++
  23.     fmt.Printf("main goroutine\:i=%d\n", i)
  24.     time.Sleep(1 \* time.Second)
  25.     }
  26.     }
复制代码

  • 开发人员无需了解任何执行细节,调度器会自动将其安排到合适的系统线程上运行
  • 如果主协程推出,所有子进程协程都会退出
  1.     package main
  2.     import (
  3.     "fmt"
  4.     "time"
  5.     )
  6.     //main()相当于是主协程
  7.     func main() {
  8.     //匿名子协程
  9.     go func() {
  10.       i := 0
  11.       for {
  12.         i++
  13.         fmt.Println("子协程 i=", i)
  14.         time.Sleep(1 \* time.Second)
  15.       }
  16.     }()
  17.     i := 0
  18.     for {
  19.       i++
  20.       fmt.Println("主协程 i=", i)
  21.       time.Sleep(1 \* time.Second)
  22.       //主协程第二次后退出
  23.       if i == 2 {
  24.         break
  25.       }
  26.     }
  27.     }
复制代码

  • 程序没任何输出,也不报错
  1.     package main
  2.     import (
  3.     "fmt"
  4.     "time"
  5.     )
  6.     //main()相当于是主协程
  7.     func main() {
  8.     //匿名子协程
  9.     go func() {
  10.     i := 0
  11.     for {
  12.     i++
  13.     fmt.Println("子协程 i=", i)
  14.     time.Sleep(1 \* time.Second)
  15.     }
  16.     }()
  17.     }
复制代码
runtime 包


  • runtime.Gosched(): 用于让出CPU时间片,调度器重新安排任务调度,还是有几率分配到它的
  1.     package main
  2.     import (
  3.     "fmt"
  4.     "runtime"
  5.     )
  6.     func main() {
  7.     //匿名子协程
  8.     go func(s string) {
  9.     for i := 0; i < 2; i++ {
  10.     fmt.Println(s)
  11.     }
  12.     }("world")
  13.     //主协程
  14.     for i := 0; i < 2; i++ {
  15.     runtime.Gosched()
  16.     fmt.Println("hello")
  17.     }
  18.     }
复制代码

  • runtime.Goexit() 立即终止当前协程
  1.     package main
  2.     import (
  3.     "fmt"
  4.     "time"
  5.     "runtime"
  6.     )
  7.     func main() {
  8.     //匿名子协程
  9.     go func() {
  10.     defer fmt.Println("A.defer")
  11.     //匿名函数
  12.     func() {
  13.     defer fmt.Println("B.defer")
  14.     //此时只有defer执行
  15.     runtime.Goexit()
  16.     fmt.Println("B")
  17.     }()
  18.     fmt.Println("A")
  19.     }()
  20.     for {
  21.     time.Sleep(time.Second)
  22.     }
  23.     }
复制代码

  • runtime.GOMAXPROCS(): 设置并行计算的CPU核数,返回之前的值
  1.     package main
  2.     import (
  3.     "runtime"
  4.     "fmt"
  5.     )
  6.     func main() {
  7.     n := runtime.GOMAXPROCS(3)
  8.     fmt.Println("n=%d\n",n)
  9.     //循环执行2个
  10.     for{
  11.     go fmt.Print(0)
  12.     fmt.Print(1)
  13.     }
  14.     }
复制代码
channel


  • goroutine运行在相同的地址空间,因此访问共享内存必须做好同步,处理好线程安全
  • goroutine奉行通过通信来共享内存,而不是共享内存通信
  • channel 是一个引用类型 用于多个goroutine 通讯 其内部实现了同步,确保并发安全
Channel  基本使用

<ul>Channel 可以用内置make() 创建
定义一个channel 也需要定义发送到channel值类型
make(chan 类型) // 无缓冲通道
make(chan 类型, 容量) // 有缓冲通道当capacity=0 时, channel 是无缓冲阻塞读写的,当capacity>0, channel 有缓冲,是非阻塞的,直到写满capacity个元素才阻塞写入
channel 通过操作符
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

西河刘卡车医

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表