第八章(并发)[三]

模式

type receiver struct {
	sync.WaitGroup
	data chan int
}

func newReceiver() *receiver {
	r := &receiver{
		data: make(chan int),
	}
	r.Add(1)
	go func() {
		defer r.Done()
		for x := range r.data {
			println("recv:", x)
		}
		/*for {
			x, ok := <-r.data //使用ok-idom读取chan 里的数据
			if !ok {
				println("data chan is closed...")
				return
			}
			println("recv:", x)
		}*/
	}()

	return r
}

func main() {
	r := newReceiver()
	r.data <- 1
	r.data <- 2
	close(r.data)
	r.Wait()
}

  • 通道本身就是一个并发安全的队列,可用作ID generator、Pool等用途
type pool chan []byte

func newPool(cap int) pool {
	return make(chan []byte, cap)
}

func (p pool) get() []byte {
	var v []byte
	select {
	case v = <-p:
	default: //通道不可用时,创建空字节切片
		v = make([]byte, 10)
	}
	return v
}
func (p pool) put(b []byte) {
	select {
	case p <- b:
	default: //通道不可用时 做其它操纵
		println("channel is full...")
	}
}
func main() {

	m := newPool(2)
	sByte1 := []byte{1, 2, 3}
	sByte2 := []byte{10, 20, 30}
	sByte3 := []byte{100, 200, 222}
	sByte4 := []byte{4, 5, 6}
	m.put(sByte1)
	m.put(sByte2)
	m.put(sByte3)
	m.put(sByte4)
        fmt.Println(m.get())
        fmt.Println(m.get())
	fmt.Println(m.get())
	fmt.Println(m.get())
	fmt.Println(m.get())
	
	/*	
		channel is full...
		channel is full...
	        [1 2 3]
		[10 20 30]
		[0 0 0 0 0 0 0 0 0 0]
		[0 0 0 0 0 0 0 0 0 0]
		[0 0 0 0 0 0 0 0 0 0]
	*/
}
  • 用通道实现信号量
func main() {
	runtime.GOMAXPROCS(4)
	wg := sync.WaitGroup{}

	sem := make(chan struct{}, 2) //最多允许2个并发同时执行

	for i := 0; i < 5; i++ {
		wg.Add(1)

		go func(id int) {
			defer wg.Done()

			sem <- struct{}{}

			defer func() { <-sem }() //释放信号
			time.Sleep(time.Second * 2)
			fmt.Println(id, time.Now())
		}(i)
	}

	wg.Wait()
}

posted @ 2023-02-02 22:52  巴达克  阅读(10)  评论(0编辑  收藏  举报