玩转Go语言之并发初体验

本文深入探讨了串行、并行和并发的概念,解释了它们在计算机科学中的意义,特别是在多线程和多核处理器环境中。文章还详细介绍了程序、进程、线程和协程的区别,并提供了在Go语言中使用协程的具体示例。
下篇更精彩!

1.明白几个概念:

串行:
    同一时刻,只有一条指令,在一个cpu上执行,后面的指令需要等到前面的指令完成之后才能执行
也就是说,程序中接口请求是一个执行完成之后,紧接着执行下一个

并行:
    同一时刻,有多条指令,在多个cpu上执行,也就是说,多个接口同时请求服务器获取数据

并发:
    同一时刻,在一条指令,在一个cpu上执行,但是cpu可以快速的在多条指令之间来回切换执行.

程序:
    编编译之后保存在磁盘上的二进制文件,会占用磁盘空间,但不会占用系统资源.

进程:
    程序在操作系统中一次执行过程,比如打开某个桌面应用,系统会开启一个进程,同一个程序可以打开多次,也就是说可以出现多个进程,进程与进程之间互不影响

线程:
    线程是进程中的一个执行实例,也就是说进程开启的同时会自动创建一个线程,主线程,进程中除了主线程,可以创建多个线程,也就是我们常说的多线程

协程:
    协程是轻量级的线程,一个线程中可以有任意多个协程,但某一时刻只能有一个协程在运行.

复制代码

2.go中怎么开启协程:

func say()  {
   for i := 0; i < 20; i++{
      fmt.Println("正在----说话")
   }
}

func eat()  {
   for i := 0; i < 20; i++{
      fmt.Println("正在++++++吃饭")
   }
}

func main() {

   go say()
   go eat()

   // 一旦主线程结束了, 那么程序就关闭了, 那么进程就不见了, 那么协程就不会被执行了
   for{
      ;
   }
}复制代码

3.怎么退出协程

func say()  {
   for i := 0; i < 20; i++{

      fmt.Println("正在----说话")
      if i== 5 {
         runtime.Goexit()
      }

   }
}

func eat()  {
   for i := 0; i < 20; i++{
      fmt.Println("正在++++++吃饭")
   }
}

func main() {

   go say()
   go eat()

   // 一旦主线程结束了, 那么程序就关闭了, 那么进程就不见了, 那么协程就不会被执行了
   for{
      ;
   }
}复制代码

4.如果同时开启多个协程,并且协程访问同一资源,那怎么保证不出错

需求1: 定义个打印的函数, 可以逐个的打印传入字符串的每个字符,在两个协程中调用这个好方法, 并且还要保持输出的内容有序的
复制代码
//创建一个互斥锁
var lock = sync.Mutex{}

func printChar(str string)  {

   //加锁,让别的协程无法访问
   lock.Lock()

   for _, ch := range str{
      fmt.Printf("%c",ch)

      time.Sleep(time.Microsecond * 300)
   }

   //解锁,让别的协程能访问
   lock.Unlock()
}

func people1()  {
   printChar("hello")
}

func people2()  {
   printChar("world")
}

func main() {

   go people1()

   go people2()

   // 一旦主线程结束了, 那么程序就关闭了, 那么进程就不见了, 那么协程就不会被执行了
   for{
      ;
   }
}复制代码
需求2:定义一个生产函数写入数据到数组,同时一个消费函数输出数组的数据,保证先生产,后消费复制代码
var buff [10] int
var lock = sync.Mutex{}

func producer()  {

   lock.Lock()

   //种随机种子
   rand.Seed(time.Now().UnixNano())
   for i := 0; i < 10; i++ {

      num := rand.Intn(100)
      fmt.Println("生产者生产了", num)

      //添加随机数
      buff[i] = num

      time.Sleep(time.Millisecond * 300)
   }

   lock.Unlock()
}

func consumer()  {

   lock.Lock()

   for i:=0; i<10;i++  {
      num := buff[i]
      fmt.Println("-------消费者消费到了", num)

      time.Sleep(time.Millisecond * 300)
   }

   lock.Unlock()
}

func main() {

   go producer()

   go consumer()

   // 一旦主线程结束了, 那么程序就关闭了, 那么进程就不见了, 那么协程就不会被执行了
   for{
      ;
   }
}

注意点: 看上去通过给生产者以及消费者同时加锁就能解决, 只有生产完了才能消费         但是取决于谁想执行加锁操作, 所以不完美.复制代码


转载于:https://juejin.im/post/5bc04b5ff265da0aac70028e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值