linux源碼分析,關鍵源碼分析

 2023-10-17 阅读 26 评论 0

摘要:SharedCalls interface提供了Do和DoEx兩種方法的抽象 // SharedCalls接口提供了Do和DoEx兩種方法 type SharedCalls interface {Do(key string, fn func() (interface{}, error)) (interface{}, error)DoEx(key string, fn func() (interface{}, error)) (interface{}, bool,
  • SharedCalls interface提供了Do和DoEx兩種方法的抽象
// SharedCalls接口提供了Do和DoEx兩種方法
type SharedCalls interface {Do(key string, fn func() (interface{}, error)) (interface{}, error)DoEx(key string, fn func() (interface{}, error)) (interface{}, bool, error)
}
  • SharedCalls interface的具體實現sharedGroup
// call代表對指定資源的一次請求
type call struct {wg  sync.WaitGroup  // 用于協調各個請求goroutine之間的資源共享val interface{}     // 用于保存請求的返回值err error           // 用于保存請求過程中發生的錯誤
}type sharedGroup struct {calls map[string]*calllock  sync.Mutex
}
  • sharedGroup的Do方法
    • key參數:可以理解為資源的唯一標識。
    • fn參數:真正獲取資源的方法。
    • 處理過程分析:
// 當多個請求同時使用Do方法請求資源時
func (g *sharedGroup) Do(key string, fn func() (interface{}, error)) (interface{}, error) {// 先申請加鎖g.lock.Lock()// 根據key,獲取對應的call結果,并用變量c保存if c, ok := g.calls[key]; ok {// 拿到call以后,釋放鎖,此處call可能還沒有實際數據,只是一個空的內存占位g.lock.Unlock()// 調用wg.Wait,判斷是否有其他goroutine正在申請資源,如果阻塞,說明有其他goroutine正在獲取資源c.wg.Wait()// 當wg.Wait不再阻塞,表示資源獲取已經結束,可以直接返回結果return c.val, c.err}// 沒有拿到結果,則調用makeCall方法去獲取資源,注意此處仍然是鎖住的,可以保證只有一個goroutine可以調用makecallc := g.makeCall(key, fn)// 返回調用結果return c.val, c.err
}
  • sharedGroup的DoEx方法
    • 和Do方法類似,只是返回值中增加了布爾值表示值是調用makeCall方法直接獲取的,還是取的共享成果
func (g *sharedGroup) DoEx(key string, fn func() (interface{}, error)) (val interface{}, fresh bool, err error) {g.lock.Lock()if c, ok := g.calls[key]; ok {g.lock.Unlock()c.wg.Wait()return c.val, false, c.err}c := g.makeCall(key, fn)return c.val, true, c.err
}
  • sharedGroup的makeCall方法
    • 該方法由Do和DoEx方法調用,是真正發起資源請求的方法。
// 進入makeCall的一定只有一個goroutine,因為要拿鎖鎖住的
func (g *sharedGroup) makeCall(key string, fn func() (interface{}, error)) *call {// 創建call結構,用于保存本次請求的結果c := new(call)// wg加1,用于通知其他請求資源的goroutine等待本次資源獲取的結束c.wg.Add(1)// 將用于保存結果的call放入map中,以供其他goroutine獲取g.calls[key] = c// 釋放鎖,這樣其他請求的goroutine才能獲取call的內存占位g.lock.Unlock()defer func() {// delete key first, done later. can't reverse the order, because if reverse,// another Do call might wg.Wait() without get notified with wg.Done()g.lock.Lock()delete(g.calls, key)g.lock.Unlock()// 調用wg.Done,通知其他goroutine可以返回結果,這樣本批次所有請求完成結果的共享c.wg.Done()}()// 調用fn方法,將結果填入變量c中c.val, c.err = fn()return c
}

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/4/142040.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息