首先非常感谢老丁和老李同学的帮助,没有他们这个问题估计又得搞很久。遇见这个问题,真是头疼。不熟悉代码、不熟悉流程,但是领导还是把活给排下来了(实在不解),只能硬着头皮找了。
问题是这样的,cache服务器中有一个存储对象的哈希表,每次访问哈希表时都要获取hash_rwlock读写锁,现在进程在获取读锁时死锁。使用gdb进入3个worker进程,发现死锁的位置都一样,都是在获取hash_rwlock读锁时阻塞住了。遇见这样的问题,加上对代码不熟,真是各种犯二。因为reload的关系,进程其实总共有9个,但是3个是一组的,所以只看了其中的一组,没有全部查看,如果全部查看的话,估计可以更早发现问题。
在同事的提醒下,先在阻塞的位置打印锁的结构,如下所示:

找了glibc的源码来看,发现pthread_rwlock_t结构的成员竟然完全没有注释,只好去看加锁、解锁的函数。在获取读锁时,只有在__writer成员为0并且__nr_writers_queued为0,即没有进程获取写锁或等待获取写锁时,才会获取锁成功。获取读锁成功后,会将__nr_readers成员加1.这么看来的话,__nr_readers存储的是当前获取读锁的进程或线程数量。在获取写锁时,只有在__writer成员为0,并且__nr_readers为0,即没有进程或线程获取写锁或读锁时,才会获取写锁成功。获取写锁成功后,会将__writer成员设置为线程ID(如果是单进程,则为进程ID),如下所示:

rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid);
最初没有注意到这行代码,自己写了一个获取写锁的测试程序,然后用gdb打印出来的。这个方法虽然笨,没有思路的时候或许着急的时候,也是不错的。
有了这些信息,再看上面的图,可以发现很多信息。__nr_readers为0,表示没有进程或线程获取hash_rwlock的读锁;__writer为12959,说明进程ID为12959的进程正在获取hash_rwlock的写锁。
现在一下子找到了方向,立马gdb进入12959进程,发现它阻塞在获取另一个进程锁process_lock(类型为pthread_mutex_t),打印process_lock,如下图所示:

   pthread_mutex_t类型中的__owner中存储的是获取当前互斥锁的进程或线程ID。找到了互斥锁的持有者,再gdb进入12960进程,发现阻塞在获取hash_rwlock读锁的位置。
至此问题就很明了了,典型的死锁。A进程获取了锁m,然后去获取另一个锁n,而B进程获取了锁n,然后去获取了另一个锁m,交叉去获取锁,都阻塞了,都在等对方释放锁。出现这种问题的原因,要么是流程设计有问题,要么就是在某个地方获取锁了之后没有正确释放。我们的这个问题就属于后者,在一个函数中在失败的时候没有释放锁就直接返回了......

利用glibc中锁结构的信息解决死锁问题的更多相关文章

  1. iOS中忽略NSLog打印信息(通过PCH文件中定义DEBUG宏解决)

    iOS中忽略NSLog打印信息 解决办法: 1.新建PrefixHeader_pch文件,在该文件中定义一下宏 //通过DEBUG宏的定义来解决Debug状态下和Release状态下的输出 #ifde ...

  2. Sql Server 中锁的概念

    锁的概述 一. 为什么要引入锁 多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: 丢失更新A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统 脏 ...

  3. Sql Server 中锁的概念(1)

    Sql Server 中锁的概念   锁的概述 一. 为什么要引入锁 多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: 丢失更新A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破 ...

  4. Java如何使用线程解决死锁?

    在Java编程中,如何使用线程解决死锁? 以下示例演示如何使用线程的概念解决死锁问题. // from W w w .Y I I b AI.c o M package com.yiibai; impo ...

  5. 如何利用Social Listening从社会化媒体中“提炼”有价值的信息?

    本文转自知乎 作者:苏格兰折耳喵 ----------------------------------------------------- 在本文中,笔者将会介绍大数据分析主要的处对象---社会化媒 ...

  6. 探索ASP.Net Core 3.0系列六:ASP.NET Core 3.0新特性启动信息中的结构化日志

    前言:在本文中,我将聊聊在ASP.NET Core 3.0中细小的变化——启动时记录消息的方式进行小的更改. 现在,ASP.NET Core不再将消息直接记录到控制台,而是正确使用了logging 基 ...

  7. Linux内核中锁机制之完成量、互斥量

    在上一篇博文中笔者分析了关于信号量.读写信号量的使用及源码实现,接下来本篇博文将讨论有关完成量和互斥量的使用和一些经典问题. 八.完成量 下面讨论完成量的内容,首先需明确完成量表示为一个执行单元需要等 ...

  8. 大话Linux内核中锁机制之完成量、互斥量

    大话Linux内核中锁机制之完成量.互斥量 在上一篇博文中笔者分析了关于信号量.读写信号量的使用及源码实现,接下来本篇博文将讨论有关完成量和互斥量的使用和一些经典问题. 八.完成量 下面讨论完成量的内 ...

  9. SQL Server中解决死锁

    SQL Server中解决死锁的新方法介绍 数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁,通过SQL Server 2005, 现在似乎有了一种新的解决办法. 将下面的 ...

随机推荐

  1. 清除大文本中的html标签

    public String clearHtmlText(String inputString) { if (StringUtils.isBlank(inputString)) { return &qu ...

  2. 伪协议触发onbeforeunload

    根据MSDN描述,IE的onbeforeunload事件触发条件: 简单点来说就是页面URL发生改变时触发: * 关闭浏览器窗口 * 点击后退.前进.刷新.主页 * 点击链接到新页面 * 调用超链接的 ...

  3. python保留两位小数

    python保留两位小数: In [1]: a = 5.026 In [2]: b = 5.000 In [3]: round(a,2) Out[3]: 5.03 In [4]: round(b,2) ...

  4. python time模块函数

    # -*-coding=utf-8 -*- __author__ = 'piay' import time def get_struct_time(): ''' 可以使用list或者字符串格式化 tm ...

  5. Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(一)

    在数据库有外键的时候,使用 select_related() 和 prefetch_related() 可以很好的减少数据库请求的次数,从而提高性能.本文通过一个简单的例子详解这两个函数的作用.虽然Q ...

  6. TCP/IP他人笔记学习--地址收录

    <TCP/IP详解,卷1:协议>学习笔记——1. 概述   http://www.blogjava.net/amigoxie/archive/2007/08/22/138674.html ...

  7. XJOI网上同步训练DAY1 T2

    思路:似曾相识?...见http://www.cnblogs.com/qzqzgfy/p/5266874.html 一看时限还是4s!,于是就开开心心地打了70%的分,就是用容斥原理,就可以n^3解决 ...

  8. 关于Yeoman使用的总结

    Yeoman由三部分组成 Yo 用于项目构建. Grunt 用于项目管理,任务制定. Bower 用于项目依赖管理. 经过一段时间的使用,对这些东西有了一些个人总结: 总体上说这些内容学习曲线略高,不 ...

  9. 使用WCF实现SOA面向服务编程—— 架构设计

    原文地址:http://www.cnblogs.com/leslies2/archive/2011/03/29/1997889.html SOA本身就是一种面向企业级服务的系统架构,简单来说,SOA就 ...

  10. Mysql update 错误

    今天在工作的时候发现自己update 一个表的某个字段超时,想了好久,首先想到的办法是,延长操作时间: mysql> set innodb_lock_wait_timeout=100 mysql ...