一、设置程序运行的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 ", intChan, &intChan) //3. 向管道写入数据 intChan<- 10 num := 211 intChan<- num intChan<- 50 // intChan<- 98//注意点, 当我们给管写入数据时,不能超过其容量 //4. 看看管道的长度和 cap(容量) fmt.Printf("channel len= %v cap=%v ", len(intChan), cap(intChan)) // 3, //5. 从管道中读取数据 var num2 int num2 = <-intChan fmt.Println("num2=", num2) fmt.Printf("channel len= %v cap=%v ", 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 可以声明为只读,或者只写性质
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 ", v) time.Sleep(time.Second) case v := <-stringChan: fmt.Printf("从 stringChan 读取的数据%s ", v) time.Sleep(time.Second) default: fmt.Printf("都取不到了,不玩了, 程序员可以加入逻辑 ") time.Sleep(time.Second) return //break label } } }