免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3045 | 回复: 9

[函数] 解锁函数pthread_mutex_unlock什么情况会失败返回? [复制链接]

论坛徽章:
0
发表于 2013-10-30 15:43 |显示全部楼层
在开发的项目中遇到一个非常怪异的问题,服务端运行好几天处理了大量的业务,表现算稳定。但是今天凌晨出现了不响应的情况,分析日志发现是死锁了。 可以确定的是这种死锁不是逻辑上的错误导致的死锁。

在锁的使用上我本着锁定尽可能少的代码的原则,所以加锁和解锁之间都是执行了少量的代码(里面也不会有嵌套的函数)。可以说pthread_mutex_lock和pthread_mutex_unlock是成对出现的。所以我可以确定没有逻辑上的死锁问题。

唯一的瑕疵是,我调用pthread_mutex_lock和pthread_mutex_unlock没有判断返回值。加锁pthread_mutex_lock是不需要判断返回值的,因为它阻塞直到可以锁定为止,一般不会有失败的情况。按理说,既然加锁成功了,那执行玩代码后接着解锁也一定能成功,所以解锁也无需判断返回值吧?
并且我认为对加锁解锁判断返回值是没什么意义的,即使返回了错误,那你又该如何处理?难道就放弃执行后面的代码了吗?

我项目中的这个死锁问题很可能是pthread_mutex_unlock调用失败了,导致下次加锁时死锁了。不知道大家是否遇到过这样的情况,如果遇到了又是如何处理的呢?

论坛徽章:
5
双鱼座
日期:2013-11-26 17:56:26狮子座
日期:2013-11-29 15:41:32处女座
日期:2014-02-21 11:59:07技术图书徽章
日期:2014-03-06 15:33:53技术图书徽章
日期:2014-03-06 15:39:30
发表于 2013-10-30 16:50 |显示全部楼层
吧mutex的属性从PTHREAD_MUTEX_NORMAL改成PTHREAD_MUTEX_ERRORCHECK试试,然后做个判断检查,一旦已经锁住返回err,就打印到Log里面去。PTHREAD_MUTEX_NORMAL当当前线程已经有锁了再锁一次应该就会被锁住的,而PTHREAD_MUTEX_ERRORCHECK会直接返回error。

       If the mutex type is PTHREAD_MUTEX_NORMAL, deadlock detection shall not be provided. Attempting to relock the mutex  causes  deadlock.
       If a thread attempts to unlock a mutex that it has not locked or a mutex which is unlocked, undefined behavior results.

       If  the  mutex type is PTHREAD_MUTEX_ERRORCHECK, then error checking shall be provided. If a thread attempts to relock a mutex that it
       has already locked, an error shall be returned. If a thread attempts to unlock a mutex that it has not locked  or  a  mutex  which  is
       unlocked, an error shall be returned.

论坛徽章:
0
发表于 2013-10-30 17:45 |显示全部楼层
回复 2# bottles


默认是PTHREAD _MUTEX_DEFAULT吧。 这种状态如果还有加锁,是在队列里排队的,解锁了就会让队首的线程先加锁。

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
发表于 2013-10-30 18:43 |显示全部楼层
double lock? double unlock ? non-initial-mutex?

论坛徽章:
5
双鱼座
日期:2013-11-26 17:56:26狮子座
日期:2013-11-29 15:41:32处女座
日期:2014-02-21 11:59:07技术图书徽章
日期:2014-03-06 15:33:53技术图书徽章
日期:2014-03-06 15:39:30
发表于 2013-10-30 21:50 |显示全部楼层
会不会由于某个线程响应了cancel pthread的消息然后退出了,但是这个时候锁还没有解锁,然后这个锁就一直挂在那里了。

论坛徽章:
1
综合交流区版块每日发帖之星
日期:2015-10-14 06:20:00
发表于 2013-10-31 12:25 |显示全部楼层
嗯  线程的东西向来难搞!    不过我认为你还是加上解锁失败检查返回值的代码,下次失败了,能看到错误信息,即使
不能最终解决问题也是能有收获的!

我还是认为能用多进程,尽量不要用多线程。这次找出问题了,下次换台机器,换个Linux内核版本,或者换到Solaris FreeBSD,出错的概率很大。

论坛徽章:
0
发表于 2013-11-01 11:16 |显示全部楼层
回复 6# fly3ds


   哎   用多进程的毛病就是通信问题,我这种需求太复杂,只能这样设计。 主进程既有单独传递给每个连接的数据,也有广播给每个连接的数据,如果一个连接一个进程,那么要创建N个共享内存/socket/pipe?  一个连接一个进程一般适用于跟父进程无额外的业务交流比较合适吧。

  所以选择多线程是比较好的方法,只要自定义数据结构,所有的线程放在一个list里面进行轮询就好了。这里要担心的就是这个list有添加、删除、读取、修改时,都要锁定。 我这个需要有较多个线程来竞争这把锁,只是我也想不出更好的模式了。

论坛徽章:
0
发表于 2013-11-01 11:21 |显示全部楼层
回复 6# fly3ds


    我这种需求的连接其实是双向服务的,既要处理来自客户端的指令(socket通信就OK了),还有响应来自服务端其他模块的触发指令(这里我选择了自己实现的缓冲队列通信模式,而抛弃了进程选择线程)。

论坛徽章:
0
发表于 2013-11-01 11:23 |显示全部楼层
回复 5# bottles


    嗯,分析过这种情况,没发现前面的指令有没处理完就退出的,都有完成工作了。

论坛徽章:
0
发表于 2013-11-01 11:27 |显示全部楼层
回复 4# linux_c_py_php


    不至于同一个线程内重复锁定,重复解锁也不会(这种情况就像重复free一样会引起崩溃)。 未初始化更不至于,倒是又可能其他变量越界,修改了互斥锁的内容(这种问题是我怀疑的,也是最麻烦的)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

SACC2019中国系统架构师大会

【数字转型 架构演进】SACC2019中国系统架构师大会,8.5折限时优惠重磅来袭!
2019年10月31日~11月2日第11届中国系统架构师大会(SACC2019)将在北京隆重召开。四大主线并行的演讲模式,1个主会场、20个技术专场、超千人参与的会议规模,100+来自互联网、金融、制造业、电商等领域的嘉宾阵容,将为广大参会者提供一场最具价值的技术交流盛会。

限时8.5折扣期:2019年9月30日前


----------------------------------------

大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP