12-Go语言进阶-02

并发编程

并发、并行

  • 并发:同一时间段,两个程序轮流执行。
  • 并行:两个程序同时执行,需要有多核CPU的支持才能实现。
    并行不一定就比并发速度快,因为线程或进程之间的通信开销很高。

进程、线程、协程

  • 进程:每个程序相当于是一个进程。一个进程包含多个线程
  • 线程:相当于轻量级的进程,相互之间通信开销小
  • 协程:相当于轻量级的线程,可以轻松的创建上百万个,没有线程切换的开销。协程的性能优势明显。

Goroutine

  • 主Goroutine的工作内容
  1. 创建一个特殊的defer语句,用于在主goroutine退出时做必要处理的善后处理
  2. 创建GC的Goroutine
  3. 执行init函数
  4. 执行main函数

如何使用Goroutine

  1. 当新的Goroutine开始时,会忽略返回值
  2. 如果main函数终止了。子goroutine也会终止了
func main() {
	go helloGo2()
	for i := 0; i < 10; i++ {
		fmt.Println("主Goroutine", i)
	}
	fmt.Println("main over")
}
func helloGo() {
	for i := 0; i < 10; i++ {
		fmt.Println("子协程", i)
	}
}
func helloGo2() {
	go helloGo()
	fmt.Println("helloGo2 over")
}

同步等待组

var wg sync.WaitGroup
func main() {
	wg.Add(2)
	go func() {
		defer wg.Done()
		for i := 0; i < 10; i++ {
			fmt.Println("A:", i)
		}
	}()
	go func() {
		defer wg.Done()
		for i := 0; i < 10; i++ {
			fmt.Println("\ta:", i)
		}
	}()
	fmt.Println("进入阻塞状态")
	wg.Wait()
	fmt.Println("都执行完了,over")
}

并发卖票

var wg2 sync.WaitGroup
var ticket = 10
var mutex sync.Mutex

func main() {
	wg2.Add(4)
	go saleTicket("站点1")
	go saleTicket("站点2")
	go saleTicket("站点3")
	go saleTicket("站点4")
	wg2.Wait()

}
func saleTicket(name string) {
	rand.Seed(time.Now().UnixNano())
	defer wg2.Done()
	for {
		mutex.Lock()
		if ticket > 0 {
			time.Sleep(time.Duration(rand.Intn(1000)) * time.Microsecond)
			fmt.Println(name, "售票", ticket)
			ticket--
		} else {
			mutex.Unlock()
			fmt.Println("售完")
			break
		}
		mutex.Unlock()
	}
}

channel

channel的读取写入是阻塞的,一对一的

func main() {
	ch1 := make(chan int)
	// 当通道关闭时,结束循环
	// v,ok := <-ch1//一般读取。ok为false,通道关闭
	go sendData(ch1)
	for v := range ch1 {
		fmt.Println("读取到的数据", v)
	}
	fmt.Println("main..over..")

}
func sendData(ch1 chan int) {
	for i := 0; i < 10; i++ {
		//写数据
		ch1 <- i
	}
	//通知对方关闭通道
	close(ch1)
}

select

func main() {
	ch1 := make(chan int)
	ch2 := make(chan int)
	go func() {
		ch1 <- 1
	}()
	select {
	case num := <-ch1:
		fmt.Println(num)
	case num2 := <-ch2:
		fmt.Println(num2)
	case <-time.After(time.Second * 0):
		fmt.Println("time")
	default:
		fmt.Println("default")
	}
}
posted @ 2022-11-16 19:34  花茶冰糖  阅读(12)  评论(0编辑  收藏  举报