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

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

使用timer.Reset()的定時器示例不按描述工作

使用timer.Reset()的定時器示例不按描述工作

Go
慕少森 2023-07-31 16:24:42
我一直在嘗試讓我的第一個“go 例程”運行的示例,當我讓它運行時,它不會按照 go 文檔中規定的帶有 timer.Reset() 函數的方式工作。就我而言,我相信我這樣做的方式很好,因為我實際上并不關心 chan 緩沖區中有什么(如果有的話)。這樣做的目的是,case <-tmr.C:如果發生任何事情,就會觸發case _, ok := <-watcher.Events:,然后一切都會安靜至少一秒鐘。這樣做的原因是,case _, ok := <-watcher.Events:事件的間隔可能是一到幾十微秒,我只關心它們全部完成并且事情再次穩定下來。然而我擔心按照文檔所說的“必須做”的方式做是行不通的。如果我知道做得更好,我會說文檔是有缺陷的,因為它假設緩沖區中有東西,而實際上可能沒有,但我不知道做得足夠好,有信心做出這樣的決定,所以我希望一些專家出來那里可以啟發我。下面是代碼。我還沒有把它放在操場上,因為我必須做一些清理(刪除對程序其他部分的調用),并且我不確定如何讓它對文件系統更改做出反應以顯示它的工作。我已經在代碼中清楚地標記了哪些替代方案有效,哪些無效。
查看完整描述

2 回答

?
HUWWW

TA貢獻1874條經驗 獲得超12個贊

例如,假設程序尚未從 tC 接收到:


if !t.Stop() {

? ? ? ? <-t.C

}

這不能與來自計時器通道的其他接收同時完成。

有人可能會說這不是一個很好的例子,因為它假設計時器在您調用時正在運行t.Stop但它確實繼續提到,如果已經有一些現有的 Goroutine 正在或可能正在讀取t.C.

Reset文檔重復了所有這些,并且順序有點錯誤,因為Reset排序在 之前Stop。)

本質上,整個地區都有點令人擔憂。沒有好的通用答案,因為在返回t.Stop呼叫期間至少存在三種可能的情況:

  • 沒有人正在收聽該頻道,并且頻道中現在沒有定時器滴答聲。如果計時器在調用之前t.Stop已停止,通常會出現這種情況。如果計時器已經停止,t.Stop則始終返回 false。

  • 沒有人正在收聽該頻道,并且頻道中現在有計時器滴答聲。當計時器正在運行但t.Stop無法阻止其觸發時,總是會出現這種情況。在這種情況下,t.Stop返回 false。當計時器正在運行但在您調用之前t.Stop就觸發了,因此它自己停止了,所以t.Stop無法停止它并返回 false。

  • 其他人正在收聽該頻道。

在最后一種情況下,您不應該執行任何操作。在第一種情況下,您不應該執行任何操作。在第二種情況下,您可能希望從通道接收以便將其清除。這就是他們的例子的目的。

有人可能會爭辯說:

if !t.Stop() {

? ? ? ? select {

? ? ? ? case <-t.C:

? ? ? ? default:

? ? ? ? }

}

是一個更好的例子。它執行一次非阻塞嘗試,該嘗試將消耗計時器滴答(如果存在),如果沒有計時器滴答,則不執行任何操作。無論您調用 時計時器是否實際運行,這都有效t.Stop。事實上,如果t.Stopreturns ,它甚至可以工作true,盡管在這種情況下,t.Stop停止了計時器,因此計時器從未設法將計時器滴答放入通道中。(因此,如果通道中存在數據,則它必然是先前清除通道失敗所遺留的。如果不存在此類錯誤,則嘗試接收也就不必要了。)


但是,如果其他人(其他一些 goroutine)正在或可能正在讀取該通道,那么您根本不應該執行此操作。盡管調用了 ,但無法知道誰(您或他們)將獲得通道中可能存在的任何計時器滴答聲Stop。


同時,如果您不打算進一步使用計時器,那么在通道中留下一個計時器滴答聲(如果有的話)相對無害。當通道本身被垃圾收集時,它也會被垃圾收集。當然,這是否明智取決于您對計時器所做的事情,但在這些情況下,只需調用t.Stop并忽略其返回值就足夠了。


查看完整回答
反對 回復 2023-07-31
?
飲歌長嘯

TA貢獻1951條經驗 獲得超3個贊

您創建一個計時器并立即停止它:

var?tmr?=?time.NewTimer(time.Second)
tmr.Stop()

這沒有任何意義,我認為這只是你的“意外”。

但更進一步,在循環內部:

????case?_,?ok?:=?<-watcher.Events:

當發生這種情況時,您聲稱這不起作用:

????????if?!tmr.Stop()?{
????????????fmt.Println(`Ticker:?CHAN?DRAIN`)
????????????<-tmr.C?//?STOPS?HERE?AND?GOES?NO?FURTHER
????????}

Timer.Stop()記錄true如果此調用停止計時器以及false計時器已停止(或到期)則返回。但是你的計時器在創建后就已經停止了,所以正確tmr.Stop()返回false,所以你進入if并嘗試從 接收tmr.C,但由于計時器“長時間”停止,因此不會在其通道上發送任何內容,因此這是一個阻塞(永遠)操作。

如果您是使用 顯式停止計時器的人timer.Stop(),則推薦的用于耗盡其通道的“模式”沒有任何意義,并且不適用于第二次調用Timer.Stop()


查看完整回答
反對 回復 2023-07-31
  • 2 回答
  • 0 關注
  • 351 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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