zoukankan      html  css  js  c++  java
  • Go语言无锁队列组件的实现 (chan/interface/select)

    1. 背景

    go代码中要实现异步很简单,go funcName()。
    但是进程需要控制协程数量在合理范围内,对应大批量任务可以使用“协程池 + 无锁队列”实现。

    2. golang无锁队列实现思路

    • Channel是Go中的一个核心类型,你可以把它看成一个管道,通过它并发核心单元就可以发送或者接收数据进行通讯(communication)。无锁队列使用带buff的chan存储数据。
    • interface{} (类似c++的void*, java的Object)可以与任意类型互转。无锁队列使用interface{}作为数据存储类型。
    • select可以处理多个信号, 可以用来解决channel阻塞问题。

    3. 代码实现

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    type DataContainer struct {
    	Queue chan interface{}
    }
    
    func NewDataContainer(max_queue_len int) (dc *DataContainer){
    	dc = &DataContainer{}
    	dc.Queue = make(chan interface{}, max_queue_len)
    	return dc
    }
    
    //非阻塞push
    func (dc *DataContainer) Push(data interface{}, waittime time.Duration) bool{
    	click := time.After(waittime)
    	select {
    	case dc.Queue <- data:
    		return true
    	case <- click:
    		return false
    	}
    }
    
    //非阻塞pop
    func (dc *DataContainer) Pop(waittime time.Duration) (data interface{}){
    	click := time.After(waittime)
    	select {
    	case data =<-dc.Queue:
    		return data
    	case <- click:
    		return nil
    	}
    }
    
    //test
    var MAX_WAIT_TIME = 10 *time.Millisecond
    func main(){
    	type dataItem struct {
    		name string
    		age int
    	}
    
    	datacotainer := NewDataContainer(2)
    	//add
    	fmt.Printf("res=%v
    ", datacotainer.Push(&dataItem{"zhangsan",25}, MAX_WAIT_TIME))
    	fmt.Printf("res=%v
    ", datacotainer.Push(&dataItem{"lisi",30}, MAX_WAIT_TIME))
    	fmt.Printf("res=%v
    ", datacotainer.Push(&dataItem{"wangwu",28}, MAX_WAIT_TIME))
    
    	//get
    	var item interface{}
    	item = datacotainer.Pop(MAX_WAIT_TIME)
    	if item != nil{
    		if tmp,ok := item.(*dataItem); ok{	//interface转为具体类型
    			fmt.Printf("item name:%v, age:%v
    ", tmp.name, tmp.age)
    		}
    	}
    }
    
  • 相关阅读:
    「UOJ#117」 欧拉回路
    「LuoguP1341」 无序字母对(欧拉回路
    「NOIP2002」「Codevs1099」 字串变换(BFS
    「IOI1998」「LuoguP4342」Polygon(区间dp
    「LuoguP2420」 让我们异或吧(树上前缀和
    「USACO13MAR」「LuoguP3080」 牛跑The Cow Run (区间dp
    「LuoguP1220」 关路灯(区间dp
    「CQOI2007」「BZOJ1260」涂色paint (区间dp
    「LuoguP1430」 序列取数(区间dp
    「USACO16OPEN」「LuoguP3147」262144(区间dp
  • 原文地址:https://www.cnblogs.com/xudong-bupt/p/10199028.html
Copyright © 2011-2022 走看看