channel随笔


/*
* A:向一个channel中不断发送数字
* B:从channel中取值,然后将值变成平方
* main: 从B中接收值进行打印
*
* */

/***
 * // channel 练习
 * func main() {
 * 	ch1 := make(chan int)
 * 	ch2 := make(chan int)
 * 	// 开启goroutine将0~100的数发送到ch1中
 * 	go func() {
 * 		for i := 0; i < 100; i++ {
 * 			ch1 <- i
 *                }
 * 		close(ch1)* 	}()
 * 	// 开启goroutine从ch1中接收值,并将该值的平方发送到ch2中
 * 	go func() {
 * 		for {
 * 			i, ok := <-ch1 // 通道关闭后再取值ok=false
 * 			if !ok {
 * 				break
 *            }
 * 			ch2 <- i * i
 *        }
 * 		close(ch2)* 	}()
 * 	// 在主goroutine中从ch2中接收值打印
 * 	for i := range ch2 { // 通道关闭后会退出for range循环
 * 		fmt.Println(i)* 	}
 * }
 */

/***
 *
 package main
 import(
 "fmt"
 "sync"
 )
 var chan1 = make(chan int ,10)
 var chan2 = make(chan int,10)
 var wg sync.WaitGroup
 func main(){
 wg.Add(2)
 go A()
 go B()
 wg.Wait()
 for i := range chan2 { // 通道关闭后会退出for range循环
 fmt.Println(i)
 }

 }

 func A(){
 defer wg.Done()
 for i:=0;i<10;i++{
 chan1 <- i
 }
    //开局就会被阻塞
    close(chan1)
 }

 func B(){
 defer wg.Done()
 for{
 i,ok:=<-chan1
 if!ok{
 break
 }
 i = i*i
 chan2<-i
 }
 //打印完会被阻塞
 close(chan2)
 }


 package main
 import(
 "fmt"

 )
 var chan1 = make(chan int ,10)

 func main(){

 close(chan1)
 i:= <-chan1
 fmt.Println(i)//0

 }


 package main
 import(
 "fmt"

 )
 var chan1 = make(chan int ,10)

 func main(){

 for i:=0;i<10;i++{
 chan1<-i
 fmt.Printf("将%d,存入channel中\n",i)
 }

 for ch := range chan1 { // 通道关闭后会退出for range循环
 fmt.Println(ch)
 }
 }



 */

/**
 channel 总共只有三总操作,发送 接收 关闭
 发送和接收都是适用<-进行操作的
 关闭通道:
    什么时候进行关闭:通知接收方,所有的数据都已经发送完毕之后需要关闭通道,通道不是一定需要关闭的,跟io不一致
    通道是可以被垃圾回收的
 关闭通道的注意事项:
    关闭一个已经关闭的通道会panic
    接收一个关闭的通道时,会取完里面所有的值,为空就返回
    接收一个关闭且没有值的通道,会取到其类型对应的零值
    像一个关闭的channel发送值会panic

 无缓冲的channel,只发会阻塞,只拿也会阻塞,必须同时有拿才不会阻塞

 channel中取值
 package main
 import(
 "fmt"

 )

 var ch1 chan int
 // channel 的取值
 func main() {
 ch1 = make(chan int,10)
 for i:=1;i<11;i++{
 ch1<-i
 }
 //循环取值的话,必须得关闭,否则会报错
 //close(ch1)
 //getByFor()
 //getByRange()
 getBySelect()

 }

 func getByFor(){
 for{
 i,ok := <-ch1
 if !ok{
 break
 }
 fmt.Println(i)
 }
 }

 func getByRange(){
 for i := range ch1{
 fmt.Printf("使用range进行取值:%d\n",i)
 }
 }

 func getBySelect(){
 for i:=0;i<11;i++{
 select{
 case x:= <-ch1:
 fmt.Printf("使用select进行取值:%d\n",x)
 default:
 fmt.Printf("使用select进行取默认值\n")
 }
 }
 }


 //从空channel中取值会死锁,但是从关闭的channel中取值,如果没有的话就是零值
 package main
 import(
 "fmt"

 )


 // channel 的取值
 func main() {
 ch1 := make(chan int,10)
 fmt.Println(ch1)
 x := <-ch1
 fmt.Println(x)
 }


加close的原因:如果不关闭,取值取不到就会死锁,

 并发和锁
 使用10个线程去卖票

 package main
 import(
 "fmt"
 "sync"

 )
 var ticket int = 10
 var wg sync.WaitGroup
 var lock sync.Mutex
 // channel 练习
 func main() {
 wg.Add(2)
 for i:=0;i<2;i++{
 go saleTicket()
 }
 wg.Wait()
 }

 func saleTicket(){
 defer wg.Done()
 for{
 lock.Lock()
 if ticket<=0{
 break
 }
 fmt.Printf("卖出第%v张票\n",ticket)
 ticket--
 lock.Unlock()
 }
 }

 var (
 x      int64
 wg     sync.WaitGroup
 lock   sync.Mutex
 rwlock sync.RWMutex
 )

 func write() {
 // lock.Lock()   // 加互斥锁
 rwlock.Lock() // 加写锁
 x = x + 1
 time.Sleep(10 * time.Millisecond) // 假设读操作耗时10毫秒
 rwlock.Unlock()                   // 解写锁
 // lock.Unlock()                     // 解互斥锁
 wg.Done()
 }

 func read() {
 // lock.Lock()                  // 加互斥锁
 rwlock.RLock()               // 加读锁
 time.Sleep(time.Millisecond) // 假设读操作耗时1毫秒
 rwlock.RUnlock()             // 解读锁
 // lock.Unlock()                // 解互斥锁
 wg.Done()
 }

 func main() {
 start := time.Now()
 for i := 0; i < 10; i++ {
 wg.Add(1)
 go write()
 }

 for i := 0; i < 1000; i++ {
 wg.Add(1)
 go read()
 }

 wg.Wait()
 end := time.Now()
 fmt.Println(end.Sub(start))
 }
 */


上一篇:安卓电脑投屏


下一篇:Ubuntu -tomcat9 更换高性能APR模式