Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 事件处理中的死锁_Go_Goroutine - Fatal编程技术网

Go 事件处理中的死锁

Go 事件处理中的死锁,go,goroutine,Go,Goroutine,因此,我有一个用于事件处理的通道,主服务器goroutine在此通道上选择,并对接收到的每个事件调用事件处理程序: evtCh := make(chan Event) // server loop: for !quit { select { case e := <- evtCh: handleEvent(e) break case quit := <-quitCh: //finish } // for send

因此,我有一个用于事件处理的通道,主服务器goroutine在此通道上选择,并对接收到的每个事件调用事件处理程序:

evtCh := make(chan Event)
// server loop:
for !quit {
    select {
    case e := <- evtCh:
        handleEvent(e)
        break
    case quit := <-quitCh:
        //finish
}

// for send a new event to processing
func addEvent(e Event) {
    evtCh <- e
}
evtCh:=make(chan事件)
//服务器循环:
对于退出{
挑选{
案例e:=
这将导致服务器挂起,因为事件处理程序本身是在服务器主循环的上下文中调用的

调用
handleEvent时,主循环不应阻塞,避免阻塞的最常见方法是使用工作进程池。下面是一个未经测试的快速示例:

type Worker struct {
    id int
    ch chan Event
    quit chan bool
}

func (w *Worker) start {
    for {
        select {
            case e := <- w.ch:
                fmt.Printf("Worker %d called\n", w.id)
                //handle event
                break;
            case <- w.quit:
                return
        }
    }
}


ch := make(chan Event, 100)
quit := make(chan bool, 0)

// Start workers
for i:=0; i<10; i++{
    worker := &Worker{i,ch,quit}
    go worker.start()
}

// 
func addEvent (e Event) {
    ch <- e
}
如果事先不知道事件的数量,您只需在退出通道上阻塞:

<- quit

要使事情更加异步,您可以

  • 为事件频道添加容量

    evtCh:=make(chan事件,10)

  • 异步调用handleEvent(e)

    go handleEvent(e)

  • 在处理程序中异步添加事件

    go addEvent(e)


或者,如果希望事件以确定性顺序处理,可以直接在处理程序中调用
handleEvent(e)
,而不是
addEvent(e)

谢谢,在这种情况下,主循环是什么样子的?您的意思是以循环方式向工作人员发送e?您不需要为循环做任何额外的事情。当您调用
addEvent(myEvent)时
第一个空闲工作线程将捕获事件。我已经用一个主线程的示例扩展了答案。我想了解为什么将
ch
设置为缓冲通道,与无缓冲通道相比有什么好处?@fluer缓冲通道将保护发送goroutine不被意外阻塞。如果偶尔,您所有的工作都会被阻塞er goroutines正忙,而您调用
addEvent()
,该调用将被阻止。缓冲通道将允许您在所有工作人员都忙的情况下将事件推送到该通道。根据规范,当通道已满时,它也将被阻止,对吗?尽管我想实际上这种可能性很小。
<- quit