GO语言进阶与依赖管理 | 青训营笔记

76 阅读2分钟

这是我参加青训营的第十二天。

并发编程

协程

协程(Goroutine)可以理解成轻量级的线程,但与线程相比,它的开销非常小。因此,Go 应用程序通常能并发地运行成千上万的协程。协程看上去和线程类似,但协程是在用户层面的,它的创建、切换、停止等等由用户操作,更“轻”  。
Go 创建一个协程非常简单,只要在方法或函数调用之前加关键字 go 即可。

为确保其完整性,我们可以利用sync方法。

package main

import (
	"fmt"
	"sync"
	"time"
)

var goRoutineWait sync.WaitGroup

func main() {
	goRoutineWait.Add(1) //即将开启一个goroutine
	//启发调用testfunc()
	go testFunc()        // 创建了协程
	goRoutineWait.Wait() //在此处等待协程任务的完成
	fmt.Println("程序运行结束")
}

func testFunc() {
	defer goRoutineWait.Done()//表示协程任务完成
	for i := 1; i <= 3; i++ {
		fmt.Printf("第%d次运行\n", i)
		time.Sleep(time.Second)
	}
}

如果想要连续并发两次,则改为goRoutineWait.Add(2)

其中开启goroutine,还可以通过匿名函数的方式。

func main() {
	goRoutineWait.Add(1)
	go func() {
	   defer goRoutineWait.Done()
	   for i := 1; i <= 3; i++ {
		  fmt.Printf("第%d次运行\n", i)
		  time.Sleep(time.Second)
	   }
	}()
	goRoutineWait.Wait()
	fmt.Println("程序运行结束")
 }

channel通道

Go语言的CSP模型通讯方式:以通信的方式共享内存数据。 协程之间传递数据需要借助通道来完成。

image.png

image.png

make(chan 元素类型,[缓冲大小])

无缓冲 make(chan int)

有缓冲 make(chan int,2)

通道分为两种:同步通道和缓冲通道。使用同步通道要求数据的发送者和接收者必须成对出现,传送时使用箭头操作符(“<-”)。传送结束后,别忘了调用 Go SDK 内置的 close 函数关闭通道,结束整个数据传送流程。

锁lock

通过锁的操作规避数据竞争,从而保护数据安全。

首先是简单的互斥锁,locker是一开头就声明的sync.Mutex变量,locker.Lock()是加锁,locjer.Unlock是解锁。但是这样的锁无法实现真正的并发,如果想要实现并发需要使用读写互斥锁。

var testInt = 0
var syncWait sync.WaitGroup
var locker sync.Mutex
func main() {
   syncWait.Add(2)
   go testFunc()
   go testFunc()
   syncWait.Wait()
   fmt.Println(testInt)
}
func testFunc() {
	defer syncWait.Done()
	defer locker.Unlock()
	locker.Lock()
	for i := 0; i < 1000; i++ {
		testInt += 1
	}
}