多线程中避免使用信号量

项目中遇到一个bug,因为接入了几家越狱平台:91、同步推、PP助手,在设备上安装了三个应用,启用其中任意一个,另外二个启动后无法创建发送socket消息,从而导致游戏直接死在登录那里,再次点击登录时线程才会被唤醒(无法发送的原因定位到,是因为在调用sem_post方法后无法将线程唤醒)。之后我尝试将信号量改为条件变量,就再也没有遇到那个问题了。具体改写的几个方法:

sem_open/sem_init => pthread_cond_init

sem_close/sem_destroy => pthread_cond_destroy

sem_wait => pthread_cond_wait

sem_post => pthread_cond_signal

信号量不仅可以用于进程也可用于线程,它比条件变量要复杂很多,条件变量仅限于线程内使用。

翻看cocos2d-x的源码中,纹理缓存用到了信号量:

//CCTextureCache.cpp
// lazy init
    if (s_pSem == NULL)
    {             
#if CC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE
        s_pSem = sem_open(CC_ASYNC_TEXTURE_CACHE_SEMAPHORE, O_CREAT, 0644, 0);
        if( s_pSem == SEM_FAILED )
        {
            CCLOG( "CCTextureCache async thread semaphore init error: %s\n", strerror( errno ) );
            s_pSem = NULL;
            return;
        }
#else
        int semInitRet = sem_init(&s_sem, 0, 0);
        if( semInitRet < 0 )
        {
            CCLOG( "CCTextureCache async thread semaphore init error: %s\n", strerror( errno ) );
            return;
        }
        s_pSem = &s_sem;
#endif

光信号量的初始化就得根据不同平台来写代码,而用条件变量进行替代则只需要一行代码,不需要针对不同的平台写不同的代码,代码量小了。

避免使用信号量,除了维护的代码较多以外,还有一个重要的原因是它容易用错。陈硕在他的著作《Linux多线程服务端编程》P85页中明确指出了,避免使用信号量(semaphore),它的功能与条件变量重合,但容易出错。在《并发编程的 15 条建议(译)》也提及如果Mutex就能解决问题,就不要使用信号量semaphore。

关于使用信号量容易出错的例子,这里倒有一个:关于sem_open(3),所有信号量这种东东最好不要在线程内使用,进程间通信就要好好去研究它了…

附:sem_open的man手册链接>>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏老码农专栏

ActFramework对模板引擎的支持与应用

22230
来自专栏小筱月

SSM整合开发

controller:作为请求转发,调用service接口处理逻辑,页面所有路径的访问方法:控制层的命名空间+@RequestMapping的value ser...

42810
来自专栏猿天地

Spring Boot Async异步执行任务

异步调用就是不用等待结果的返回就执行后面的逻辑,同步调用则需要等带结果再执行后面的逻辑。

18420
来自专栏coolblog.xyz技术专栏

Spring MVC 原理探秘 - 一个请求的旅行过程

22740
来自专栏李家的小酒馆

Spring MVC面试整理

Spring MVC执行过程 1. 客户端的请求提交到dispatcherServlet 2. DispatcherServ...

29000
来自专栏技术墨客

Spring核心——数据校验

在Java数据校验详解中详细介绍了Java数据校验相关的功能(简称Bean Validation,涵盖JSR-303、JSR-349、JSR-380),本文将在...

67120
来自专栏黑泽君的专栏

day32_Hibernate学习笔记_04

  缓存(Cache):是计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写硬盘(永久性数...

10320
来自专栏菩提树下的杨过

gradle项目中资源文件的相对路径打包处理技巧

开发java application时,不管是用ant/maven/gradle中的哪种方式来构建,通常最后都会打包成一个可执行的jar包程序,而程序运行所需的...

87850
来自专栏美码师

补习系列-springboot mime类型处理

MIME的全称是Multipurpose Internet Mail Extensions,即多用途互联网邮件扩展,尽管读起来有些拗口,但大多数人可能都知道, ...

21120
来自专栏康怀帅的专栏

Memcached 使用详解

以 PHP 为例使用 Memcached。 系统类 $m=new Memcached(); $m->addServer('memcached',11211);...

27570

扫码关注云+社区

领取腾讯云代金券