GO语言学习笔记之协程和管道

一、设置程序运行的CPU数量

package main

import (
	"fmt"
	"runtime"
)

func main() {
	//获取当前系统CPU的数量
	num:=runtime.NumCPU()
	//设置num-1的cpu运行程序
	//runtime.GOMAXPROCS(num-1)
	fmt.Println(num)
}

二、使用互斥锁解决资源竞争的问题

package main

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

var(
	mp =make(map[int]int,10)
	lock sync.Mutex
)

func test(n int){
	lock.Lock()
	mp[n]=n
	lock.Unlock()
}

func main() {
	for i:=0;i<200;i++{
		go test(i)
	}
	time.Sleep(time.Second*10)
	for i:=0;i<200;i++{
		fmt.Println(mp[i])
	}
}

三、使用管道channel解决资源竞争的问题

package main
import ( "fmt"
)
func main() {
	//演示一下管道的使用
	//1. 创建一个可以存放 3 个 int 类型的管道
	var intChan chan int
	intChan = make(chan int, 3)
	//2. 看看 intChan 是什么
	fmt.Printf("intChan 的值=%v intChan 本身的地址=%p\n", intChan, &intChan)
	//3. 向管道写入数据
	intChan<- 10
	num := 211
	intChan<- num
	intChan<- 50
	// intChan<- 98//注意点, 当我们给管写入数据时,不能超过其容量
	//4. 看看管道的长度和 cap(容量)
	fmt.Printf("channel len= %v cap=%v \n", len(intChan), cap(intChan)) // 3,
	//5. 从管道中读取数据
	var num2 int
	num2 = <-intChan
	fmt.Println("num2=", num2)
	fmt.Printf("channel len= %v cap=%v \n", len(intChan), cap(intChan)) // 2, 3
	//6. 在没有使用协程的情况下,如果我们的管道数据已经全部取出,再取就会报告 deadlock
	//num3 := <-intChan
	//num4 := <-intChan
	//num5 := <-intChan
	//fmt.Println("num3=", num3, "num4=", num4, "num5=", num5)
}

四、遍历管道

package main

import "fmt"

func main() {
	var arr chan int
	arr=make(chan int,100)
	for i:=1;i<101;i++{
		arr<-i*5
	}
	close(arr)//遍历管道必须关闭,否则会报错deadlock
	for v:=range arr{
		fmt.Println(v)
	}
}

五、channel使用注意事项和细节

1) channel 可以声明为只读,或者只写性质

GO语言学习笔记之协程和管道

 

2)使用 select 可以解决从管道取数据的阻塞问题

package main
import ( "fmt"
	"time"
)
func main() {
	//使用 select 可以解决从管道取数据的阻塞问题
	//1.定义一个管道 10 个数据 int
	intChan := make(chan int, 10)
	for i := 0; i < 10; i++ {
		intChan <- i
	}
	//2.定义一个管道 5 个数据 string
	stringChan := make(chan string, 5)
	for i := 0; i < 5; i++ {
		stringChan <- "hello" + fmt.Sprintf("%d", i)
	}
	//传统的方法在遍历管道时,如果不关闭会阻塞而导致 deadlock
	//问题,在实际开发中,可能我们不好确定什么关闭该管道. //可以使用 select 方式可以解决
	//label:
	for {
		select {
		//注意: 这里,如果 intChan 一直没有关闭,不会一直阻塞而 deadlock
		//,会自动到下一个 case 匹配
		case v := <-intChan:
			fmt.Printf("从 intChan 读取的数据%d\n", v)
			time.Sleep(time.Second)
		case v := <-stringChan:
			fmt.Printf("从 stringChan 读取的数据%s\n", v)
			time.Sleep(time.Second)
		default:
			fmt.Printf("都取不到了,不玩了, 程序员可以加入逻辑\n")
			time.Sleep(time.Second)
			return
			//break label
		}
	}
}

  

 

上一篇:Asp.Net MVC<三> : ASP.NET MVC 基本原理及项目创建


下一篇:Zotero,一款爱不释手的文献管理软件