Go并发

1.WaitGroup等待当前运行的协程

package main

import (
	"fmt"
	"runtime"
	"sync"
)

// Go语言的并发指的是能让某个函数独立于其他函数运行的能力
// Go的调度器是在操作系统之上的
//Go的并发同步模型来自一个叫做通信顺序进程(CSP)的东西
//同步和传递数据的关键数据类型是通道
func main() {
	// 分配一个逻辑处理器给调度器使用
	runtime.GOMAXPROCS(1)

	//wg用来等待程序完成
	//计数加2,表示要等待2个goroutine
	var wg sync.WaitGroup
	wg.Add(2)
	fmt.Println("Start Goroutines")

	//声明一个匿名函数,创建一个goroutine
	go func() {
		// 在函数退出时调用Done来同志main函数工作已经完成
		defer wg.Done()
		for count := 0; count < 3; count++ {
			for char := 'a'; char < 'a'+26; char++ {
				fmt.Printf("%c ", char)
			}
		}

	}()

	go func(){
		defer wg.Done()
		for count := 0; count < 3; count++ {
			for char := 'A'; char < 'A'+26; char++ {
				fmt.Printf("%c ", char)
			}
		}

	}()

	//等待goroutine结束
	fmt.Println("Waiting To Finish")
	wg.Wait()
	fmt.Println("\nTerminating Program")
}

2.互斥锁
在对共享资源进行计算的时候使用

package main

import (
	"fmt"
	"runtime"
	"sync"
)

var (
	// counter是所有goroutines都要增加其值的变量
	counter int
	// wg用来等待程序结束
	wg sync.WaitGroup
	// mutex用来定义一段代码临界区
	mutex sync.Mutex
)

func main() {
	// 计数为2,表示要等待两个goroutines
	wg.Add(2)
	go incCounter(1)
	go incCounter(2)
	wg.Wait()
	fmt.Printf("Final Counter: %d\n",counter)


}

func incCounter(id int){
	defer wg.Done()
	for count:=0;count<2;count++{
		// 同一时刻只允许一个goroutine进入
		// 这个是临界区
		mutex.Lock()
		{
			//捕获counter的值
			value:=counter
			// 当前goroutines从线程退出,并放回到队列
			runtime.Gosched()

			//增加本地的value变量的值
			value++
			counter = value
		}
		mutex.Unlock()
		//释放锁,允许其他正在等待的goroutine
		//进入临界区
	}
}
mutex.Lock(){}的花括号只是为了方便看,可以省略。

3.无缓冲通道的使用

package main

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

//var wg sync.WaitGroup
//
//func main() {
//	// 创建一个无缓冲的通道
//	baton := make(chan int)
//
//	// 为最后一位跑步者将计数加1
//	wg.Add(1)
//	//第一位跑步者持有接力棒
//	go Runner(baton)
//	// 第一位选手接棒
//	baton <- 1
//	wg.Wait()
//
//}
//
//func Runner(baton chan int) {
//	var newRunner int
//	// 等待接力棒
//	runner := <-baton
//
//	// 开始绕着跑道跑步
//	fmt.Printf("Runner %d Running With Baton\n", runner)
//	if runner != 4 {
//		newRunner = runner + 1
//		fmt.Printf("Running %d To Rhe Line\n", newRunner)
//		go Runner(baton)
//	}
//	time.Sleep(1000 * time.Millisecond)
//	//比赛结束了么
//	if runner == 4 {
//		fmt.Printf("Runner %d Finished,Race Over\n", runner)
//		defer wg.Done()
//		return
//	}
//	fmt.Printf("Runner %d Exchange with Runner %d\n", runner, newRunner)
//	baton <- newRunner
//}

var wg sync.WaitGroup

func main() {
	//创建一个无缓冲的通道
	baton:=make(chan int)
	wg.Add(1) 
	go Runner(baton) //第一位跑步者持有接力棒
	baton<-1 //开始比赛
	wg.Wait() //等待比赛结束
}

func Runner(baton chan int ){
	var newRunner int
	runner:=<-baton
	fmt.Printf("第 %d 位选手开始跑\n",runner)
	if runner!=4{
		newRunner = runner+1
		fmt.Printf("第 %d 位选手准备\n",runner)
		go Runner(baton)

	}
	time.Sleep(1000*time.Millisecond)
	if runner==4{
		fmt.Printf("第%d位选手到达终点,比赛结束")
		wg.Done() //完成的时候调用
	}
	//交给下一位
	baton<-newRunner

}

来源:Go in Action

posted @ 2020-12-01 11:45  公众号python学习开发  阅读(88)  评论(0编辑  收藏  举报