• 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
    ", 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
    		}
    	}
    }
    

      

  • 相关阅读:
    linux--文件夹下批量改动IP
    Effective C++ 条款24
    ARMv8 Linux内核异常处理过程分析
    VS2010升级VS2013后,出现没有定义类型“PowerPacks.ShapeContainer”错误解决方法
    利用Nginx构建负载均衡server
    getline与get函数的区别
    Linking Containers Together
    获取不同机型外置SD卡路径
    查看linux系统状态
    Linux 开机自检的设置(tune2fs和fsck)
  • 原文地址:https://www.cnblogs.com/mango1997/p/15524936.html
Copyright © 2020-2023  润新知