亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Golang 睡眠線程而不是忙于等待

Golang 睡眠線程而不是忙于等待

Go
jeck貓 2022-05-10 13:33:42
我正在編寫Leslie Lamport's Bakery algorithm的 Go 實現,它有忙自旋等待來處理最大數量的線程。我正在編寫一個 go 函數,除非滿足特殊條件,否則該函數不應繼續執行。到目前為止,我的代碼如下所示:func acquireLock() {    ...    for specialConditionIsFalse {    }    ...}有沒有更有效的方法來停止處理這個線程?
查看完整描述

2 回答

?
holdtom

TA貢獻1805條經驗 獲得超10個贊

這里有幾點值得注意:

  1. goroutines 不是線程。沒有“goroutine 數量”,系統中的 goroutine 數量也沒有固定的上限。1 可以修改 Bakery 算法以處理動態創建的線程(使用列表或映射,如 Wikipedia 頁面上的 Java 示例),但對每個“線程”有一個唯一 ID 的強烈要求,這使得這不是一個一般而言,Go 的好主意。(您可以依次使用實現類似線程行為的包來解決這個問題,包括線程 ID。)

  2. 正如維基百科頁面所指出的:

    Lamport 的面包店算法假設一個順序一致性內存模型。很少有(如果有的話)語言或多核處理器實現這樣的內存模型。因此,算法的正確實現通常需要插入柵欄來禁止重新排序。

    這意味著您將需要使用該sync/atomic包,這違背了編寫自己的鎖定的目的。

有了這兩個巨大的警告,你可以調用runtime.Gosched()你會調用 POSIX 樣式yield()函數的地方,或者你可以使用一個通道來表示有人“離開了面包店”,因此輪到下一個用戶了。但是渠道本身會完成您需要的所有互斥。一個簡化的特定于 Go 的非 Lamport 面包店算法是微不足道的(但以下所有內容都未經測試):

var takeANumber chan int64

var currentlyServing int64


init() {

    takeANumber = make(chan int64)

    go giveNumbers()

}


// giveNumbers hands out ever-increasing ticket numbers

func giveNumbers() {

    for int64 i := 0;; i++ {

        takeANumber <- i

    }

}


// WaitTurn gets a ticket, then waits until it is our turn.  You can

// call this "Lock" if you like.

func WaitTurn() int64 {

    ticket := <-takeANumber

    for atomic.LoadInt64(&currentlyServing) < ticket {

        runtime.Gosched()

    }

    return ticket

}


// ExitBakery relinquishes our ticket, allowing the next user to proceed.

func ExitBakery(ticket int64) {

    atomic.StoreInt64(&currentlyServing, ticket + 1)

}

將其修改為使用兩個通道,以便該WaitTurn功能更有效,留作練習。(當然,除了作為練習之外,沒有理由一開始就使用這些代碼。)


1您可以設置運行時限制,但如果您調用任何阻塞系統調用,系統無論如何都會產生額外的 goroutine。阻塞的系統調用集以及何時調用它們取決于運行時,因此您無法對此進行真正的控制,至少在不編寫特定于平臺的代碼的情況下是無法控制的。


查看完整回答
反對 回復 2022-05-10
?
ibeautiful

TA貢獻1993條經驗 獲得超6個贊

在當前版本中,goroutine 不是可搶占的。這意味著如果你有一個緊密循環的 goroutine,那么這個 goroutine 不會將它正在運行的線程讓給其他 goroutine。有時這可能意味著沒有其他 goroutine 將永遠運行。

不要像這樣忙著等待,而是使用一個頻道:

<-specialCondition
// Do stuff

并在特殊情況發生時關閉它。

您也可以嘗試使用 a sync.Cond,但您可以使用通道執行條件變量所做的所有事情。



查看完整回答
反對 回復 2022-05-10
  • 2 回答
  • 0 關注
  • 181 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號