说一说ffmpeg到处都在使用的ff_thread_once函数
從名字就能知道ff_thread_once函數(shù)的作用,就是保證在多線(xiàn)程調(diào)用的時(shí)候,函數(shù)只執(zhí)行一次
FFmpeg中是使用經(jīng)典的double check來(lái)保證函數(shù)只執(zhí)行一次的,我們來(lái)跟蹤下函數(shù)看下具體的實(shí)現(xiàn):
ff_thread_once函數(shù)是調(diào)用pthread_once函數(shù)實(shí)現(xiàn)的:
pthread_once函數(shù)實(shí)現(xiàn)如下:
static av_always_inline int pthread_once(pthread_once_t *once_control,void (*init_routine)(void)) {if (!once_control->done){_fmutex_request(&once_control->mtx, 0);if (!once_control->done){init_routine();once_control->done = 1;}_fmutex_release(&once_control->mtx);}return 0; }
可以看到代碼中有兩處對(duì)done是否為1進(jìn)行檢查的地方,很多人剛開(kāi)始看到這個(gè)代碼可能感到很奇怪,為什么同樣的值要檢查兩次,其實(shí)這就是double check的實(shí)現(xiàn)。
假設(shè)現(xiàn)在多個(gè)線(xiàn)程同時(shí)調(diào)用函數(shù) pthread_once,這個(gè)時(shí)候第一個(gè)先執(zhí)行的先檢查done是否為1,為0的時(shí)候在獲取鎖,獲取鎖成功了在檢查一次done是否為0,只有這時(shí)還是為0的時(shí)候才調(diào)用函數(shù), 這樣就能保證只有一個(gè)線(xiàn)程能執(zhí)行到init_routine函數(shù)。連個(gè)檢查缺一不可。
第一個(gè)線(xiàn)程獲取到鎖之后,在執(zhí)行done是否為0的檢查時(shí),第二個(gè)線(xiàn)程會(huì)在獲取鎖的地方死等,直到上一個(gè)線(xiàn)程執(zhí)行結(jié)束釋放鎖之后,第二個(gè)線(xiàn)程才能獲取到鎖,然后檢查done已經(jīng)為1,就釋放鎖退出,雖然這樣能保證函數(shù)init_routine()只執(zhí)行了一次,但是由于每個(gè)調(diào)用pthread_once的函數(shù)都得獲取一次鎖,存在競(jìng)爭(zhēng)的時(shí)候還得等待,這樣在成千上萬(wàn)的線(xiàn)程的服務(wù)器中,是不能接受的。加上1就能解決這個(gè)問(wèn)題
在第一個(gè)線(xiàn)程檢車(chē)到done為0,然后獲取到鎖,線(xiàn)程1的時(shí)間片結(jié)束,內(nèi)核將執(zhí)行權(quán)交給線(xiàn)程2,線(xiàn)程2檢查done為0,然后獲取鎖,因?yàn)榫€(xiàn)程1已經(jīng)拿到鎖了,所以線(xiàn)程2就主動(dòng)丟掉執(zhí)行權(quán),將執(zhí)行權(quán)交出,線(xiàn)程1執(zhí)行結(jié)束之后釋放鎖, 這個(gè)時(shí)候線(xiàn)程2拿到鎖,因?yàn)闆](méi)有標(biāo)號(hào)2的檢查,所有也調(diào)用了一次init_routine(), 這樣就和設(shè)計(jì)的初衷相違背了。
總結(jié)
以上是生活随笔為你收集整理的说一说ffmpeg到处都在使用的ff_thread_once函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 作者:刘诗凯(1983-),男,华为大数
- 下一篇: 作者:吴甘沙,男,现任英特尔中国研究院院