多线程调试—原理与实践

简介: 多线程调试—原理与实践

背景

最近搜索在切换新搜索平台,在切换过程中发现一个case会在检索过程中触发coredump。借助这个case详细讲述下GDB和线程调度的细节,进而更好的理解多线程调试。

正文

搜索系统收到检索请求,会将请求按照库进行任务分解,放到任务队列,线程池中的工作线程拿到任务执行检索。本次出现coredump的点就是工作线程执行的代码。

对于多线程调试就涉及到一个概念All-Stop Mode。先按下这个概念不提,如果没有设置All-Stop Mode,就进行调试,会发生什么:

(gdb) break word_element.cpp:39
Breakpoint 1 at 0x109b5dc: file word_element.cpp, line 39.
(gdb) c
Continuing.
[New Thread 0x7fca27926700 (LWP 76457)]
[New Thread 0x7fca27125700 (LWP 76458)]
[Switching to Thread 0x7fca27926700 (LWP 76457)]
Breakpoint 1, WordElement::Reset (this=0x3a5fe020, node=...) at word_element.cpp:39
39     word_element.cpp: No such file or directory.
(gdb) print node.PrintDebugString()
[Switching to Thread 0x7fca27125700 (LWP 76458)]
Breakpoint 1, WordElement::Reset (this=0x44b21420, node=...) at word_element.cpp:39
39     in word_element.cpp
The program stopped in another thread while making a function call from GDB.
(google::protobuf::Message::PrintDebugString() const) will be abandoned.
When the function is done executing, GDB will silently stop.

由于执行函数调用,当前进程因为另外一个线程执行而停止,调试进行不下去了。回到刚刚的概念

什么是“All-Stop Mode”?

GDB无法单步调试所有线程,由于线程的调度策略取决于调试的操作系统,当调试线程执行一步时,其他线程可能执行不止一条语句。当调试线程continue或者单步执行时,一旦其他线程在当前线程的执行结束之前触发断点、异常、信号,可能会发现程序终止(program stopped)。由于触发,GDB会自动切换到触发线程并提示“ [Switching to Thread n]”。因此,如果想要顺利调试需要使用“set scheduler-locking on”锁定操作系统调度器,只允许调试线程执行。

(gdb) break word_element.cpp:39
Breakpoint 1 at 0x109b5dc: word_element.cpp, line 39.
(gdb) c
Continuing.
[New Thread 0x7f42de3af700 (LWP 52695)]
[New Thread 0x7f42ddbae700 (LWP 52696)]
[Switching to Thread 0x7f42de3af700 (LWP 52695)]
Breakpoint 1, WordElement::Reset (this=0x42c76020, node=...) at word_element.cpp:39
39     word_element.cpp: No such file or directory.
(gdb) set scheduler-locking on
(gdb) print node.PrintDebugString()
node_level: 3
node_weight: 0.49673182
hit_field: 0

如上,就可以愉快的排查堆栈,查看coredump发生的原因了

本文作者 : cyningsun

本文地址https://www.cyningsun.com/10-11-2017/multithread-debug.html

版权声明 :本博客所有文章除特别声明外,均采用 CC BY-NC-ND 3.0 CN 许可协议。转载请注明出处!

相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
2月前
|
存储 监控 Java
Java多线程优化:提高线程池性能的技巧与实践
Java多线程优化:提高线程池性能的技巧与实践
63 1
|
2月前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
2月前
|
编解码 网络协议 API
Netty运行原理问题之Netty的主次Reactor多线程模型工作的问题如何解决
Netty运行原理问题之Netty的主次Reactor多线程模型工作的问题如何解决
|
18天前
|
存储 缓存 Java
什么是线程池?从底层源码入手,深度解析线程池的工作原理
本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
什么是线程池?从底层源码入手,深度解析线程池的工作原理
|
10天前
|
Java 程序员
Java中的多线程基础与实践
【9月更文挑战第21天】本文旨在引导读者深入理解Java多线程的核心概念,通过生动的比喻和实例,揭示线程创建、同步机制以及常见并发工具类的使用。文章将带领读者从理论到实践,逐步掌握如何在Java中高效地运用多线程技术。
|
8天前
|
Java 调度 开发者
Java中的多线程编程:从基础到实践
本文旨在深入探讨Java多线程编程的核心概念和实际应用,通过浅显易懂的语言解释多线程的基本原理,并结合实例展示如何在Java中创建、控制和管理线程。我们将从简单的线程创建开始,逐步深入到线程同步、通信以及死锁问题的解决方案,最终通过具体的代码示例来加深理解。无论您是Java初学者还是希望提升多线程编程技能的开发者,本文都将为您提供有价值的见解和实用的技巧。
15 2
|
10天前
|
Java 数据处理
Java中的多线程编程:从基础到实践
本文旨在深入探讨Java中的多线程编程,涵盖其基本概念、创建方法、同步机制及实际应用。通过对多线程基础知识的介绍和具体示例的演示,希望帮助读者更好地理解和应用Java多线程编程,提高程序的效率和性能。
18 1
|
5天前
|
Java 数据处理 调度
Java中的多线程编程:从基础到实践
本文深入探讨了Java中多线程编程的基本概念、实现方式及其在实际项目中的应用。首先,我们将了解什么是线程以及为何需要多线程编程。接着,文章将详细介绍如何在Java中创建和管理线程,包括继承Thread类、实现Runnable接口以及使用Executor框架等方法。此外,我们还将讨论线程同步和通信的问题,如互斥锁、信号量、条件变量等。最后,通过具体的示例展示了如何在实际项目中有效地利用多线程提高程序的性能和响应能力。
|
7天前
|
存储 缓存 Java
JAVA并发编程系列(11)线程池底层原理架构剖析
本文详细解析了Java线程池的核心参数及其意义,包括核心线程数量(corePoolSize)、最大线程数量(maximumPoolSize)、线程空闲时间(keepAliveTime)、任务存储队列(workQueue)、线程工厂(threadFactory)及拒绝策略(handler)。此外,还介绍了四种常见的线程池:可缓存线程池(newCachedThreadPool)、定时调度线程池(newScheduledThreadPool)、单线程池(newSingleThreadExecutor)及固定长度线程池(newFixedThreadPool)。
|
2月前
|
Java 调度
Java中的多线程基础与实践
【8月更文挑战第31天】本文将深入浅出地讲解Java中多线程的基础知识,并通过实例展示如何在Java程序中实现多线程。我们将从多线程的基本概念出发,逐步深入到线程的创建、控制以及同步机制,最后通过一个简易版的生产者消费者模型来实践这些知识点。文章旨在帮助初学者快速掌握多线程编程的关键技能,并理解其背后的原理。