go语言并发编程(一)

一、 协程Goroutine

通常情况下,程序在运行时只有一条主协程,按照顺序的形式来进行执行。 当我们想让程序的两个函数及多个函数进行并发 执行时,需要在函数名前加上关键字go,来为程序建立一个子协程。在子协程结束后,主协程才会结束。

通常,应用在Web服务器端来给用户提供信息。

import "fmt"
import "time"
func showMessage(msg string){
	for i:=0 ; i<=6 ; i++ {
		fmt.Printf("msg: %v\n", msg)
		time.Sleep(time.Millisecond * 1000)
	}
}
func main(){
 	go showMessage("hello") // go 启动了一个子协程
 	showMessage("world")
 	// defer showMessage("!!!") 当函数执行到return 才来执行defer关键字以来延迟执行
}

二、 通道channel

当程序中建立了多个协程后,各个协程之间需要进行数据通信,这就需要通道channel(管道),保证数据同步交换。
通道在使用时,也需要给它进行类型设置。什么样的类型通道就传递什么样的类型数据。
通道在使用时,也分为无缓冲和有缓冲的;无缓冲的通道在数据交换时是可以立即发生的而缓冲通道不行,有缓冲的通道是用于执行异步通信。
通道的发送和接收特性:

  • 对于同一个通道而言,发送和接受数据的操作都是互斥的
  • 发送和接受数据进行元素值的处理时都是不可分割的
  • 发送和接受操作在完全完成之后会被阻塞
// 使用make来创建通道,chan关键字来指定通道类型
var UnChannel = make(chan int, 0) // int类型的无缓冲通道, 第二个参数默认为0
var Channel = make(chan string, 10) //string类型的缓冲通道,缓冲区设置为10个  

// 发送信息到通道
// 设置一个随机数
rand.Seed(time.Now().UnixNano())
values := rand.Intn(100) // 随机一个100以内的整数
UnChannle <- values // 发送到信道

value := <- UnChannle // 从通道中接收信息
// 实现对channel的遍历1) 使用for_if来进行遍历
(2) 使用for_range方式来进行遍历
var c = make(chan int)
go func(){
	for i:=0; i<100; i++ {
		c <- i
	}
	close(c)
}() // 调用自己

for v := range(c){
	fmt.Printf("v: %v\n", v)
}

三、 实现协程同步 (WaitGroup)

需要导入包:

import “sync”

当我们的程序中进行多个协程时,有时往往会使我们的子协程还未完全执行时,主协程就已经调用,而使得部分子协程的功能没有显示出来。此时就需要我们加入同步机制来保证程序的执行。

var swg sync.WaitGroup

func test(i int){
	defer swg.Done() // 等待协程结束,登记为-1; 与wg.Add(-1)的功能一样
	fmt.Printf("hello 子协程: %v\n", i+1)
}
func main(){
	for i:=0; i<10; i++ {
		swg.Add(1) // 启动一个协程goroutine登记为+1
		go test(i)
	}
	
	swg.Wait()  //等待所有的协程结束后才执行
}

四、使用runtime包

runtime包中用来协调协程的运行,主要通过Gosched()方法来实现
Gosched() 主要是 " 牺牲自己,奉献别人 ", 把自己的CPU资源转让给别的协程来执行, 最后才执行自己。

当遇到某些条件,需要退出某个协程时,可以执行runtime.Goexit() 方法来退出当前协程。

可以使用 runtime.GOMAXPROCS(i) 来设置CPU的数量,当i=1时,也想要实现协程并行,则需要对每个协程设置上睡眠 time.Sleep(time.MillSecond * 100)

func test(str string){
	for i:=0; i<10; i++ {
		fmt.Println(s)	
	}
}

func main(){
	go test("GO") // 子协程
	
	// 主协程
	for i:=0; i<2; i++ {
		runtime.Gosched() // 转让CPU资源
		fmt.Println("golang")
	}
}

你可能感兴趣的:(go并发,golang,开发语言,后端)