簡體   English   中英

帶有緩沖通道的死鎖

[英]Deadlock with buffered channel

我有一些代碼是作業調度程序,正在整理來自許多TCP套接字的大量數據。 這段代碼是使用大量瞬態對象的方法的結果-避免了爭用,並且在很大程度上降低了CPU使用率並且現在鎖定也不是問題。

我的應用程序有時會鎖定,並且“通道長度”日志是唯一重復發生的事情,因為仍然有數據從我的套接字輸入。 但是,計數仍為5000,並且不進行任何下游處理。

認為問題可能是競賽情況,並且可能掛斷的線路是jobDispatcher select中的channel <- msg jobDispatcher 問題是我不知道如何驗證這一點。

我懷疑由於select可以隨機獲取項目,因此goroutine正在返回,shutdownChan沒有機會進行處理。 然后數據命中inboundFromTCP並阻塞!

可能有人在這里發現了明顯錯誤的地方。 並希望提供解決方案!?

var MessageQueue = make(chan *trackingPacket_v1, 5000)

func init() {
    go jobDispatcher(MessageQueue)
}

func addMessage(trackingPacket *trackingPacket_v1) {
    // Send the packet to the buffered queue!
    log.Println("Channel length:", len(MessageQueue))
    MessageQueue <- trackingPacket
}

func jobDispatcher(inboundFromTCP chan *trackingPacket_v1) {
    var channelMap = make(map[string]chan *trackingPacket_v1)

    // Channel that listens for the strings that want to exit
    shutdownChan := make(chan string)

    for {
        select {
        case msg := <-inboundFromTCP:
            log.Println("Got packet", msg.Avr)
            channel, ok := channelMap[msg.Avr]
            if !ok {
                packetChan := make(chan *trackingPacket_v1)

                channelMap[msg.Avr] = packetChan
                go processPackets(packetChan, shutdownChan, msg.Avr)
                packetChan <- msg
                continue
            }
            channel <- msg
        case shutdownString := <-shutdownChan:
            log.Println("Shutting down:", shutdownString)
            channel, ok := channelMap[shutdownString]
            if ok {
                delete(channelMap, shutdownString)
                close(channel)
            }
        }
    }
}

func processPackets(ch chan *trackingPacket_v1, shutdown chan string, id string) {
    var messages = []*trackingPacket_v1{}

    tickChan := time.NewTicker(time.Second * 1)
    defer tickChan.Stop()

    hasCheckedData := false

    for {
        select {
        case msg := <-ch:
            log.Println("Got a messages for", id)
            messages = append(messages, msg)
            hasCheckedData = false
        case <-tickChan.C:

            messages = cullChanMessages(messages)
            if len(messages) == 0 {
                messages = nil
                shutdown <- id
                return
            }

            // No point running checking when packets have not changed!!
            if hasCheckedData == false {
                processMLATCandidatesFromChan(messages)
                hasCheckedData = true
            }
        case <-time.After(time.Duration(time.Second * 60)):
            log.Println("This channel has been around for 60 seconds which is too much, kill it")
            messages = nil
            shutdown <- id
            return
        }
    }
}

更新01/20/16

我嘗試將channelMap用作帶有一些互斥鎖的全局對象,但最終仍然死鎖。


稍微調整了代碼,仍然鎖定,但我不知道這是怎么做的! https://play.golang.org/p/PGpISU4XBJ


更新01/21/17在提出一些建議之后,我將其放入一個獨立的工作示例中,以便人們看到。 https://play.golang.org/p/88zT7hBLeD

這是一個長期運行的過程,因此在游樂場將其殺死時,需要在計算機上本地運行。 希望這可以幫助您找到根底!

我猜測您的問題在另一個goroutine正在執行shutdown <- id的同時,正在執行此channel <- msg -msg。

由於channelshutdown通道均未緩沖,因此它們阻塞了等待接收器的時間。 他們可以陷入僵局,等待另一邊變得可用。

有幾種解決方法。 您可以使用緩沖區1聲明這兩個通道。

或者,您可以執行Google的上下文包的操作,並通過關閉關閉通道來發送關閉信號,而不是通過發送關閉消息來發出信號。 查看https://golang.org/pkg/context/,尤其是WithCancelWithDeadlineDone函數。

您可能可以使用上下文來刪除自己的關閉通道和超時代碼。

JimB提出了在可能仍在通道上接收goroutine的同時將其關閉的觀點。 您應該執行的操作是發送關閉消息(或關閉或取消上下文),並繼續處理消息,直到關閉您的ch通道(以case msg, ok := <-ch: ,這將在發送方收到關機信息。

這樣,您將獲得所有傳入的消息,直到實際發生關閉為止,並且應該避免再次出現死鎖。

我是Go的新手,但是在這里的代碼中

case msg := <-inboundFromTCP:
        log.Println("Got packet", msg.Avr)
        channel, ok := channelMap[msg.Avr]
        if !ok {
            packetChan := make(chan *trackingPacket_v1)

            channelMap[msg.Avr] = packetChan
            go processPackets(packetChan, shutdownChan, msg.Avr)
            packetChan <- msg
            continue
        }
        channel <- msg

您不是在這里放一些東西(無緩沖嗎?)

channel, ok := channelMap[msg.Avr]

因此,在添加味精之前,您是否需要清空該頻道?

channel <- msg

就像我說的那樣,我是Go的新手,所以我希望自己不要傻。 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM