Singleflight防擊穿

此功能參考了groupcache源碼

import "sync"

// call is an in-flight or completed Do call
type call struct {
    wg  sync.WaitGroup
    val interface{}
    err error
}

// Group represents a class of work and forms a namespace in which
// units of work can be executed with duplicate suppression.
type Group struct {
    mu sync.Mutex       // protects m
    m  map[string]*call // lazily initialized
}

// Do executes and returns the results of the given function, making
// sure that only one execution is in-flight for a given key at a
// time. If a duplicate comes in, the duplicate caller waits for the
// original to complete and receives the same results.
//同一個(gè)對象多次同時(shí)多次調(diào)用這個(gè)邏輯的時(shí)候,可以使用其中的一個(gè)去執(zhí)行
func (g *Group) Do(key string, fn func()(interface{},error)) (interface{}, error ){
    g.mu.Lock() //加鎖保護(hù)存放key的map,因?yàn)橐l(fā)執(zhí)行
    if g.m == nil { //lazing make 方式建立
        g.m = make(map[string]*call)
    }
    if c, ok := g.m[key]; ok { //如果map中已經(jīng)存在對這個(gè)key的處理那就等著吧
        g.mu.Unlock() //解鎖少办,對map的操作已經(jīng)完畢
        c.wg.Wait()
        return c.val,c.err //map中只有一份key,所以只有一個(gè)c
    }
    c := new(call) //創(chuàng)建一個(gè)工作單元申鱼,只負(fù)責(zé)處理一種key
    c.wg.Add(1)
    g.m[key] = c //將key注冊到map中
    g.mu.Unlock() //map的操做完成,解鎖
    
    c.val, c.err = fn()//第一個(gè)注冊者去執(zhí)行
    c.wg.Done()
    
    g.mu.Lock()
    delete(g.m,key) //對map進(jìn)行操作云头,需要枷鎖
    g.mu.Unlock()
    
    return c.val, c.err //給第一個(gè)注冊者返回結(jié)果
}

測試函數(shù)

func TestDoCopy(t *testing.T) {
    var g Group
    c := make(chan string)
    var calls int32
    fn := func()(interface{},error) {
        atomic.AddInt32(&calls,1)
        return <-c , nil
    }

    var wg sync.WaitGroup
    for i:= 0; i< 10 ;i++ {
        wg.Add(1)
        go func(){
            v, err := g.Do("key",fn)
            if err != nil {
                t.Errorf("exec fn error =%v", err)
            }
            if v.(string) != "bar" {
                t.Errorf("got %q; want %q", v, "bar")
            }
            wg.Done()
        }()
    }

    time.Sleep(1000* time.Millisecond)
    c <- "bar"
    wg.Wait()

    if got := atomic.LoadInt32(&calls); got != 1 {
        t.Errorf("number of calls = %d; want 1", got)
    }
 return     
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捐友,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子溃槐,更是在濱河造成了極大的恐慌匣砖,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異脆粥,居然都是意外死亡砌溺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門变隔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蟹倾,你說我怎么就攤上這事匣缘。” “怎么了鲜棠?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵肌厨,是天一觀的道長。 經(jīng)常有香客問我豁陆,道長柑爸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任盒音,我火速辦了婚禮表鳍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘祥诽。我一直安慰自己譬圣,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布雄坪。 她就那樣靜靜地躺著厘熟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪维哈。 梳的紋絲不亂的頭發(fā)上绳姨,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機(jī)與錄音阔挠,去河邊找鬼飘庄。 笑死,一個(gè)胖子當(dāng)著我的面吹牛谒亦,可吹牛的內(nèi)容都是我干的竭宰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼份招,長吁一口氣:“原來是場噩夢啊……” “哼切揭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起锁摔,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤廓旬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體孕豹,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涩盾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了励背。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片春霍。...
    茶點(diǎn)故事閱讀 39,795評論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖叶眉,靈堂內(nèi)的尸體忽然破棺而出址儒,到底是詐尸還是另有隱情,我是刑警寧澤衅疙,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布莲趣,位于F島的核電站,受9級特大地震影響饱溢,放射性物質(zhì)發(fā)生泄漏喧伞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一绩郎、第九天 我趴在偏房一處隱蔽的房頂上張望潘鲫。 院中可真熱鬧,春花似錦嗽上、人聲如沸次舌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彼念。三九已至,卻和暖如春浅萧,著一層夾襖步出監(jiān)牢的瞬間逐沙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工洼畅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吩案,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓帝簇,卻偏偏與公主長得像徘郭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子丧肴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容