日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

在Go語言中,程序的并發(fā)操作是通過通道(channel)來實(shí)現(xiàn)的。通道是用來傳遞數(shù)據(jù)的一種特殊類型,它可以在goroutine之間進(jìn)行數(shù)據(jù)交換和通信。然而,如果在程序中使用單通道進(jìn)行工作,并在引入新通道時(shí)沒有正確處理,就有可能導(dǎo)致死鎖現(xiàn)象的發(fā)生。本文將由php小編小新為大家詳細(xì)解釋Go程序中單通道工作和死鎖問題,以及如何避免死鎖的發(fā)生。

問題內(nèi)容

我是Go通道的新手,我正在嘗試通過構(gòu)建模擬內(nèi)核并通過通道處理交互來學(xué)習(xí)Go通道。此示例程序的目標(biāo)是讓多個(gè)進(jìn)程 (2) 使用單通道同時(shí)向內(nèi)核發(fā)送內(nèi)存分配請(qǐng)求,其他進(jìn)程發(fā)送釋放內(nèi)存請(qǐng)求 使用單個(gè)但不同的通道到內(nèi)核。

+-------------+
                           +------------------+       |             |
                          -> Alloc. Mem. Ch.  |-->|   Kernel    |
|   Process A     | |  Realse Mem. Ch. |<      |             |
                           +------------------+       +-------------+

登錄后復(fù)制

如果我只有分配請(qǐng)求,程序就可以工作,一旦我引入釋放請(qǐng)求,程序就會(huì)陷入死鎖。

請(qǐng)注意,進(jìn)程在發(fā)送分配請(qǐng)求時(shí)也會(huì)創(chuàng)建一個(gè)回復(fù)隊(duì)列,但是,這在上圖中沒有顯示,因?yàn)樗皇菃栴}的一部分。

完整的程序如下:

package main

import (
        "fmt"
        // "log"
        "time"
)

const (
        _ float64 = iota
        LowPrio
        MedPrio
        HghPrio
)

// Kernel type to communicate between processes and memory resources
type Kernel struct {
        reqMemCh chan chan int
        rlsMemCh chan int
}

func (k *Kernel) Init() {
        k.reqMemCh = make(chan chan int, 2)
        k.rlsMemCh = make(chan int, 2)
        go k.AllocMem()
        go k.RlsMem()
}

// Fetch memory on process request
func (k *Kernel) GetReqMemCh() chan chan int {
        return k.reqMemCh
}

func (k *Kernel) GetRlsMemCh() chan int {
        return k.rlsMemCh
}

func (k *Kernel) AllocMem() {
        // loop over the items (process reply channels) received over
        // the request channel
        for pCh := range k.GetReqMemCh() {
                // for now think 0 is the available index
                // send this as a reply to the exclusive process reply channel
                pCh <- 0
                close(pCh)
        }
}

// Release memory
func (k *Kernel) RlsMem() {
        // we do not have to anything here
}

// Process type which requests memory
type Proc struct {
        ind     int
        prio    float64
        exeT    time.Time
        count   int
        memInd  int
        rqMemCh chan chan int
        rlMemCh chan int
}

func (p *Proc) Init(
        ind int,
        prio float64,
        rqMemCh chan chan int,
        rlMemCh chan int,
) {
        p.ind = ind
        p.prio = prio
        p.memInd = -1
        p.rqMemCh = rqMemCh
        p.rlMemCh = rlMemCh
}

func (p *Proc) GetReqMemCh() chan chan int {
        return p.rqMemCh
}

func (p *Proc) GetRlsMemCh() chan int {
        return p.rlMemCh
}

func (p *Proc) ReqMem() {
        // create the reply channel exclusive to the process
        // this channel will return the allocated memeory id/address
        rpCh := make(chan int)
        // send the reply channel through the request channel
        // to get back the allocation memory id
        p.GetReqMemCh() <- rpCh
        // Below line is blocking ...
        for mi := range rpCh {
                p.memInd = mi
        }
}

func (p Proc) RlsMem() {
        p.GetRlsMemCh() <- 0
}

func (p Proc) String() string {
        return fmt.Sprintf(
                "Proc(%d): Memory(%d), Count(%d)",
                p.ind+1, p.memInd+1, p.count,
        )
}

func main() {

        k := &Kernel{}
        k.Init()

        p := &Proc{}
        for i := 0; i < 3; i++ {
                p.Init(i, LowPrio, k.GetReqMemCh(), k.GetRlsMemCh())
                p.ReqMem()
                p.RlsMem()
        }

        time.Sleep(time.Second)
}

登錄后復(fù)制

異常情況如下:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.Proc.RlsMem(...)
        main.go:100
main.main()
        main.go:119 +0xc5

goroutine 6 [chan receive]:
main.(*Kernel).AllocMem(0x0?)
        main.go:41 +0x5e
created by main.(*Kernel).Init in goroutine 1
        main.go:25 +0xc5
exit status 2

登錄后復(fù)制

任何幫助將不勝感激。

干杯,

DD。

解決方法

作為英國人評(píng)論,您有一個(gè)緩沖通道已達(dá)到其容量,但沒有任何內(nèi)容可供讀取。

根據(jù)語言之旅 (1 2),發(fā)送和接收塊,直到另一方準(zhǔn)備好。雖然緩沖通道在這里提供了一些寬容,但一旦緩沖區(qū)已滿,行為是相同的。

可以通過添加 k.rlsMemCh 的使用者來解決此問題。如果您沒有為此計(jì)劃任何操作,請(qǐng)刪除該通道或暫時(shí)使用邏輯將其耗盡。

func (k *Kernel) Init() {
        k.reqMemCh = make(chan chan int, 2)
        k.rlsMemCh = make(chan int, 2)
        go k.AllocMem()
        go k.RlsMem()
}

func (k *Kernel) AllocMem() {
        for pCh := range k.GetReqMemCh() {
                pCh <- 0
                close(pCh)
        }
}

func (k *Kernel) RlsMem() {
        // TODO: Add a for-select or for-range over k.rlsMemCh here
}

登錄后復(fù)制

排水可能如下所示:

func (k *Kernel) RlsMem() {
        for {
                <-k.GetRlsMemCh()
        }
}

登錄后復(fù)制

分享到:
標(biāo)簽:Go語言 overflow
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定