从名字就能知道ff_thread_once函数的作用,就是保证在多线程调用的时候,函数只执行一次

FFmpeg中是使用经典的double check来保证函数只执行一次的,我们来跟踪下函数看下具体的实现:
ff_thread_once函数是调用pthread_once函数实现的:

#define ff_thread_once(control, routine) pthread_once(control, routine)

pthread_once函数实现如下:

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;
}


可以看到代码中有两处对done是否为1进行检查的地方,很多人刚开始看到这个代码可能感到很奇怪,为什么同样的值要检查两次,其实这就是double check的实现。
假设现在多个线程同时调用函数 pthread_once,这个时候第一个先执行的先检查done是否为1,为0的时候在获取锁,获取锁成功了在检查一次done是否为0,只有这时还是为0的时候才调用函数, 这样就能保证只有一个线程能执行到init_routine函数。连个检查缺一不可。

  1. 假设缺少1,
    第一个线程获取到锁之后,在执行done是否为0的检查时,第二个线程会在获取锁的地方死等,直到上一个线程执行结束释放锁之后,第二个线程才能获取到锁,然后检查done已经为1,就释放锁退出,虽然这样能保证函数init_routine()只执行了一次,但是由于每个调用pthread_once的函数都得获取一次锁,存在竞争的时候还得等待,这样在成千上万的线程的服务器中,是不能接受的。加上1就能解决这个问题
static av_always_inline int pthread_once(pthread_once_t *once_control,void (*init_routine)(void))
{_fmutex_request(&once_control->mtx, 0);if (!once_control->done){init_routine();once_control->done = 1;}_fmutex_release(&once_control->mtx);return 0;
}
  1. 假设缺少2
    在第一个线程检车到done为0,然后获取到锁,线程1的时间片结束,内核将执行权交给线程2,线程2检查done为0,然后获取锁,因为线程1已经拿到锁了,所以线程2就主动丢掉执行权,将执行权交出,线程1执行结束之后释放锁, 这个时候线程2拿到锁,因为没有标号2的检查,所有也调用了一次init_routine(), 这样就和设计的初衷相违背了。
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);init_routine();once_control->done = 1;_fmutex_release(&once_control->mtx);}return 0;
}

说一说ffmpeg到处都在使用的ff_thread_once函数相关推荐

  1. 宜信创始人唐宁:技术到处都是,关键看怎么用

     宜信创始人唐宁:技术到处都是,关键看怎么用 极客公园 2017-06-02 16:15 阅读:4443 摘要:作者:「痛点是什么?」5月26日下午的北大斯坦福中心,这是宜信创始人唐宁口中出现频率 ...

  2. 最近大街上,到处都是X团的地推

    小文说,最近大街上,到处都是X团的地推,成群结队的,拉着每一个路人推销他们的软件,忽悠着你下载他们的APP. 小文昨天中午出去吃饭,五.六个X团的地推,把一个漂亮女孩围在中间,各个都是轻佻的语气,拜托 ...

  3. 不要到处都用@Autowired啦

    相信大部分人项目只要用了spring框架,肯定到处都是@Autowired. 注意: spring4.3以后就可以省略@Autowired了,全部更新内容: 地址:其中跟新内容如下 这是什么意思呢,翻 ...

  4. 小学生python-小学生都能学会的python(函数)

    小学生都能学会的python(函数) 神马是函数 函数: 对功能或者动作的封装 函数的定义 def 函数名(形参列表): 函数体(return) ret = 函数名(实参列表) 函数的返回值 retu ...

  5. 【Android FFMPEG 开发】Android Studio 工程配置 FFMPEG ( 动态库打包 | 头文件与函数库拷贝 | CMake 脚本配置 )

    文章目录 I . FFMPEG 交叉编译后的函数库及头文件 II . FFMPEG 静态库打包动态库 ( 仅做参考 ) III . 创建 Android Studio 工程 IV . FFMPEG 头 ...

  6. 小学生在家自学python_小学生都能学会的python(函数)

    小学生都能学会的python(函数) 神马是函数 函数: 对功能或者动作的封装 函数的定义 def 函数名(形参列表): 函数体(return) ret = 函数名(实参列表) 函数的返回值 retu ...

  7. c语言中ch1和ch2是什么意思,2020-05-26(C语言)1.将串str中所有值为ch1的字符转换成ch2的字符,如果str为空串,或者串中不含值为ch1的字符,则什么都不做.2.逆转函数...

    //1.将串str中所有值为ch1的字符转换成ch2的字符,如果str为空串,或者串中不含值为ch1的字符,则什么都不做.2.逆转函数 include include define MAXLEN 25 ...

  8. 我对NHibernate的感受(2):何必到处都virtual

    上一篇主要是在夸NHibernate实现的好,而这篇就完全是来抱怨的了.NHiberante有个毛病,就是如果是和数据库产生映射的类,就要求所有的public成员和protected成员必须是virt ...

  9. NHibernate :何必到处都virtual

    上一篇文章主要是在夸NHibernate实现的好,而这篇就完全是来抱怨的了.NHiberante有个毛病,就是如果是和数据库产生映射的类,就要求所有的public成员和protected成员必须是vi ...

最新文章

  1. php 正则中文匹配
  2. jsp 环境配置记录
  3. python getattr_python __getattr__ 巧妙应用
  4. 五花八门的bug跟踪工具
  5. JVM 垃圾回收算法及回收器详解
  6. SDNU 1423.入学考试(01背包)
  7. 借助HiddenText 确定CheckBoxList当前的操作类型及点击的CheckBox
  8. 十大因素——造就优秀的董事长
  9. 要学会“收”和“放”
  10. 基于Java的对称加密算法和非对称加密算法
  11. 求职面试过程中都需要注意哪些
  12. app 播放服务器文件,配置apple-app-site-association文件并在服务器上传
  13. Debian10上使用360随身Wifi
  14. 教你看懂ACC、TJA、 ICA、ICC 这些功能都能干些啥
  15. TransOMCS:从语言图提取常识知识
  16. java频繁的读写文件_大量较为频繁读写的文件一般如何进行存储?
  17. 工信部通报下架60款APP:关联有赞、三六零、唯品会等上市公司
  18. 国内做数据可视化大屏哪家强?这5款产品你必须了解
  19. 守护进程--day33
  20. springboot+flowable请假详细流程

热门文章

  1. 代码质量随想录(五)注得多不如注得巧
  2. Kickstart 多系统安装配置
  3. IBM公司扩展云平台 计划推出SmartCloud
  4. linux看3D实景
  5. JSP简单练习-省略显示长字符串
  6. 项目上传github步骤
  7. nodejs 利用zip-local模块压缩文件夹
  8. 常用,好用的js代码
  9. Callable、Future、FutureTask浅析
  10. Java实现敏感词过滤 - IKAnalyzer中文分词工具