Java Socket「饥饿死锁」问题

关于http socket timeout 超时时间 未设置 导致线程一直在等待(线程饥饿),微信公众号开发过程遇到的。java 问题:http socket timeout 未设置 导致线程饥饿  1、我使用的是微信提供的包 maven坐标:                               me.chanjar                   weixin-java-mp                   1.3.3              里面是有了httpclient 阅读详情

前言

Socket是指网络上端到端的通信机制,一般基于传输层协议。本文以Java为例,专门讨论TCP协议的Socket,UDP协议的Socket也可以参考。

饥饿-读

考虑这样一个情况:一个简单的HTTP客户端访问服务器资源的程序在运行了一段时间后,莫名的停住了;或者是一个简单的JDBC查询数据库记录的程序在运行了一段时间后,没有动静了。此时,dump下Java目前的运行状态,基本上能看到如下代码片段:

Thread %d: (state = IN_NATIVE)
 - java.net.SocketInputStream.socketRead0(java.io.FileDescriptor, byte[], int, int, int) @bci=0 (Compiled frame; information may be imprecise)
 - java.net.SocketInputStream.read(byte[], int, int, int) @bci=87 (Compiled frame)
 - java.net.SocketInputStream.read(byte[], int, int) @bci=11 (Compiled frame)
 - java.net.SocketInputStream.read(byte[]) @bci=5 (Compiled frame)
 - ... ... ...

多次dump发现,进程一直阻塞在socketRead0函数,也就是说进程已经「饿死」了。至于为什么会「饥饿」到死,这个原因就复杂了,可能是服务端自己产生了死锁,也可能是服务端运行异常,跳过了往客户端发送数据的代码。但是作为客户端,读不到数据可能不是最糟糕的,最糟糕的是阻塞导致其它代码不能执行。
这就需要打破这种阻塞状态。Java的Socket API 提供了这个机制。

void setSoTimeout(int timeout) 

Socket的setSoTimeout方法,用于设置读取超时,单位是毫秒。默认情况下,值为0,即无限等待直到读取数据。如果设置为一个合理的值,比如30000,则读取超时为30秒,即30秒之后,如果数据还未到达,则抛出一个超时异常。

HTTP和JDBC底层都是基于TCP的Socket机制实现,所以不管是HTTP客户端,还是JDBC客户端,一般都会提供这个参数的配置。

死锁-写

死锁-写有一个经典的场景。
Server端 ↓

public class Server {

    public static void main(String[] args) throws Exception {
        int count = 0;
        ServerSocket ss = new ServerSocket(6060);
        Socket s = ss.accept();
        while (true) {
            s.getOutputStream().write(new byte[1024 * 8]);
            s.getInputStream().read();
            System.out.println("server: " + ++count);
        }
    }
}

Client端 ↓

public class Client {

    public static void main(String[] args) throws Exception {
        int count = 0;
        Socket s = new Socket("localhost", 6060);
        while (true) {
            s.getOutputStream().write(new byte[1024 * 8]);
            s.getInputStream().read();
            System.out.println("client: " + ++count);
        }
    }
}

两个程序运行几次后,就不再打印任何消息了,即两个进程处于死锁状态了。造成死锁的原因自然是满足了死锁的四个必要条件:

  • 互斥;Server端和Client端都既是生产者,也是消费者,互斥的使用两个TCP缓冲队列。
  • 请求与保持;由于write方法每次写8KB,而read方法每次只读1B,所以两个缓冲队列都很快被填满。此时,两端都请求空的缓冲区,并保持着对方空缓冲的释放权利。
  • 不剥夺;这两个程序请求资源是非抢占式的,显然不会被剥夺。
  • 环路等待;Server端和Client端的程序都阻塞在write,互相等待对方释放空的缓冲区。

解决死锁的办法也很简单,将write和read分离在不同的线程,写归写,读归读,打破环路等待的条件。那样虽然读的比较慢,但死锁是不存了。

将读写分离成不同线程时,需要特别注意:不要在Socket对象上加同步锁。这样跟不分离没有实质上的区别。

结论

Socket编程一般都是多进程编程(服务端和客户端),多线程编程(Socket发送接收一般都是独立线程)的综合。所以,多进程、多线程的各种编程问题层出不穷,最突出的就是饥饿和死锁,需要足够多的代码来沉淀。

从进程资源图到死锁:核心概念、化简算法与实战排查指南 在并发编程与操作系统领域,资源竞争是核心挑战之一,其理论基础源于进程资源图这一形式化模型。该模型通过图形化方式描述进程与资源间的申请与占有关系,是分析系统资源分配状态的基石。其核心原理在于通过化简算法对资源分配图进行推演,判断系统是否存在安全序列,从而评估死锁风险。这项技术的工程价值在于,它为诊断和预防因互斥、持有等待、不可抢占及循环等待四大条件同时满足而引发的死锁问题,提供了系统性的分析方法。在实际应用场景中,无论是数据库事务锁竞争、多线程编程中的锁顺序问题,还是分布式系统中的资源协调,理解并应用进程资源 阅读详情

相关推荐

Java实现的多线程聊天室简易教程

本文还有配套的精品资源,点击获取 简介:本项目通过Java编程语言实现了一个简易的多线程聊天室,涉及到网络编程、并发处理和用户交互等核心领域。项目重点在于Java Socket编程、多线程处理和聊天室的基本功能实现,包括用户登录、消息发送/接收和退出聊天室。通过源代码分析,学习者可以掌握如何创建和管理线程、网络通信以及聊天室消息传递机制。 1. Java Sock...

weixin_33239721的博客 1426

java进程假死_java进程假死

进程假死,查看dump信息如下Attaching to process ID 24746, please wait...Debugger attached successfully.Server compiler detected.JVM version is 25.101-b13Deadlock Detection:No deadlocks found.Thread 6886: (state =...

weixin_31550647的博客 1044

C#实战:如何用winmm.dll打造毫秒级高精度定时器(附完整代码)

本文详细介绍了在C#中利用winmm.dll实现毫秒级高精度定时器的完整方案。针对.NET内置定时器精度不足的问题,通过调用timeSetEvent等原生API,提供了超越系统时钟中断周期的精准定时能力。文章包含核心原理剖析、完整的封装类代码以及音视频处理、游戏开发等场景下的实战应用与性能调优指南。

ujm5678901的博客 690

【help】JVM的CPU资源占用过高问题的排查

JVM的CPU资源占用过高问题的排查 jstack命令格式: jstack [ option ] pid 参数说明: -F jstack [-l] pid无法响应时,强制打印堆栈 -l l长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表. -m 混合模式输出(包括java和本地c/c++片段)堆栈。 pid: java应用程序的进程号 参数是互斥的,不能联合使用。 jstack生成的Thread Dump日志结构解析 jsta

掘金者说 770

八股文(Unity篇)

在Unity中,协程是通过迭代器实现的,即将协程函数的返回值类型定义为IEnumerator,然后使用yield语句暂停协程的执行,并在需要恢复执行时通过MoveNext()方法继续执行。Unity中的协程是一种能够在主函数中暂停和恢复执行的功能,它使用了C#的迭代器。Resources方式:Resources方式:使用Resources.Load方法加载Resources文件夹下的资源,这种方式的好处是简单易用,无需手动打包资源,但是会导致应用包变得较大,加载速度较慢,不适合较大的资源文件。

m0_50816320的博客 1万+

图像修复黑科技:对比BM3D/DnCNN等5种去噪器在PNP框架中的实战效果

本文深度评测了BM3D、DnCNN等五款主流去噪器在即插即用(PnP)优化框架中的实战表现。通过量化指标、视觉对比及超分等泛化任务测试,揭示了深度学习模型在性能与收敛速度上的优势,并为不同应用场景提供了选型指南与工程化建议。

weixin_29065959的博客 367

深入理解JVM - JVM常用命令

jps(JVM Process Status Tool):显示指定系统内所有的HotSpot虚拟机进程 jstat(JVM Statistics Monitoring Tool):用户收集HotSpot虚拟机各方面的运行数据 jinfo(Configuration Info for Java):实时查看和调整虚拟机各项参数,在JDK9中集成到了jhsdb jmap(Memory Map for ...

xiaolyuh的专栏 1595

瑞数jsvmp算法还原流程讲解

​ 又是很久没写文章了,今天水一篇文章吧,鉴于之前有看到过别人的文章被警告的案例,所以这篇文章就仅写一下还原瑞数vmp的大概流程吧(仅记录下自己还原的思路)

博客 6607

JDBC未设置socket超时导致应用程序的线程池阻塞

应用阻塞,查看堆栈 https://www.jianshu.com/p/2deaf51bf715

shy_snow的专栏 1556

【知识分享】CAN总线中终端网络的重要性

P沟道和N沟道晶体管的漏源通态电阻匹配良好时,形成的CANH和CANL信号匹配良好;如果驱动器的一半具有比另一半低得多的导通状态电阻,那么总线共模电压将从VCC/2的显性状态偏离,并回到VCC/2的隐性状态,这将导致每一次状态转换都会伴随着共模电压噪声,从而导致更高水平的传导和辐射能量发射。

一只豌豆象的博客 1543

1. SAP Fiori Elements 开发环境的搭建和开发准备工作

本文介绍了本地使用 Visual Studio Code 进行 Fiori Elements 开发所需要安装的这个扩展包里6个能够提高 Fiori Elements 应用开发效率的扩展。在本教程后续步骤里我们会通过实际的例子介绍这些 Visual Studio Code 扩展的详细用法。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 3451

java.net.SocketInputStream.socketRead0 挂起线程

背景 现在的Java EE 系统通常都依赖于远程服务,需要通过网络请求获取远程服务。不管是使用什么协议(HTTP,HTTPS,JDBC 等)请求远程服务,Java VM最终都将委托给Socket去实现。首先会通过connect方法与远程服务建立连接,连接建立成功后就可以 write/read 与远程服务实现数据通信。 Socket.connect()、Socket.write()、Socket.r...

回归心灵的专栏 4万+

【Simulink教程案例9】基于simulink的BPSK,QPSK调制解调通信系统建模与仿真——使用simulink自带模块设计

BPSK (Binary Phase Shift Keying)-------二进制相移键控。是把模拟信号转换成数据值的转换方式之一,利用偏离相位的复数波浪组合来表现信息键控移相方式。BPSK使用了基准的正弦波和相位反转的波浪,使一方为0,另一方为1,从而可以同时传送接受2值(1比特)的信息。BPSK的映射关系如下所示:BPSK调制过程将输入的1010二进制数据中的0都转化为-1,使得非极性码变为极性码。

FPGA/MATLAB学习教程/源码/项目合作开发 3484

关于http socket timeout 超时时间 未设置 导致线程一直在等待(线程饥饿),微信公众号开发过程遇到的。java...

为什么80%的码农都做不了架构师?>>> ...

weixin_34355881的博客 652

【视频监控国标GB/T28181】无人机的视频图传技术

然而,随着无人机市场的不断发展和无人机视频图传技术的迅速进步,一些厂家正积极探索更多的传输方式。如今,一些大疆无人机已经具备了4G辅助图传功能,这意味着它们需要在无人机上安装相应的SIM卡,并在有移动互联网信号的情况下,通过互联网进行视频图传。这种技术的应用,不仅提高了无人机的操作灵活性,也使得无人机在各个领域的应用更加广泛。在使用时,用户需时刻注意无人机的飞行距离。在无人机图传系统中,OFDM技术的运用更是如虎添翼,显著增强了视频传输的品质与稳定性,尤其在错综复杂的电磁环境中,更能凸显其不可替代的优势。

开源物联网项目商业化作者 5661

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Java程序阻塞问题排查:从线程状态分析到死锁解决方案

程序阻塞是多线程编程中的常见问题,其本质是线程因资源竞争或等待而无法继续执行。从技术原理看,线程在Java中可能处于BLOCKED、WAITING或TIMED_WAITING状态,这些状态反映了线程因锁竞争、资源等待或网络超时等原因被挂起。理解线程状态机制对于诊断程序'走不了'问题具有重要价值,特别是在高并发场景下能有效识别死锁和资源耗尽风险。在实际应用中,通过jstack工具分析线程堆栈可以快速定位阻塞点,结合死锁检测算法能系统性地解决多线程协同问题。本文基于线程状态监控和死锁预防策略,为Java开发者提

weixin_34347651的博客 400

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Java线程问题排查利器:jstack原理、实战与高阶应用

在Java应用性能调优与故障排查领域,线程状态分析是定位问题的核心基础。通过理解线程的RUNNABLE、BLOCKED、WAITING等状态及其转换原理,可以快速诊断程序卡顿、资源争用等并发问题。这一技术对于保障高并发服务的稳定性具有关键价值,广泛应用于在线服务性能瓶颈分析、死锁检测等场景。本文聚焦于JDK内置的jstack工具,它通过获取Java进程的线程栈快照,为上述分析提供原始数据。结合实战案例,文章详细解读了如何利用jstack输出的线程状态与栈信息,关联操作系统线程ID(nid),定位高CPU消耗

weixin_33739646的博客 436

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

【温故而知新】Java多线程&并发(十)

61、线程其他方法 1. sleep():强迫一个线程睡眠N毫秒。 2. isAlive(): 判断一个线程是否存活。 3. join(): 等待线程终止。 4. activeCount(): 程序中活跃的线程数。 5. enumerate(): 枚举程序中的线程。 6. currentThread(): 得到当前线程。 7. isDaemon(): 一个线程是否为守护线程。 8. setDaemon(): 设置一个线程为守护线程。 (用户线程和守护线程的区别在于,是否...

581

KOSync 进度同步的 CFI↔XPointer 跨章解析:Readest 中 spine index 解析原理与 scroll-lag 陷阱修复

本篇技术指南围绕 Readest(基于 foliate-js 的跨平台电子书阅读器)与 KOReader KOSync 协议之间的进度双向同步展开,深入解析 CFI(foliate 格式)与 XPointer(KOReader CREngine 格式)的换算机制,以及一个极易踩中的陷阱:`view.renderer.primaryIndex` 在连续滚动模式下会滞后于视口,导致按"当前主视图"构造

gitblog_00067的博客 324

多线程编程(2)—线程安全

1. 问题的引出 比奇小说网 https://m.biqi.org/  线程安全归根结底可以说是内存安全,在jvm内存模型中,有一块特殊的公共内存空间,称为堆内存,进程内的所有线程都可以访问并修改其中的数据,就会造成潜在的问题。因为堆内存空间在没有保护机制的情况下,你放进去的数据,可能被别的线程篡改。如下代码: public class ThreadSafe implements Ru...

代码小牛的博客 251

java中关于线程的安全问题

一、锁有哪些? 1.共享锁: 多个线程可以同时读 数据,但是读的时候不允许写,其他线程写的时候也不允许读,更不可以同时写数据。 2.排它锁: 多个线程不可以同时进行,必须等上一个线程完成下一个线程才能进行 3.公平锁: 多个线程排队访问同步资源,非公平锁每次都是重新抢夺资源,可能造成饥饿线程。 二、synchronized的用法和意思 1.synchronized代表锁和同步的意思 2.synchronized可以写在实例方法上,代表锁对象为this 3.synchronized可以写在静态方法上,代表锁对

qq_42674061的博客 161

Java线程面试及答案--面试必看

这是博主精心准备的各厂线程面试都可能涉及的问题及答案,接下来让我们一起看看都是些什么问题吧。 1.简述线程的生命周期 线程是一个动态执行的过程,它也有一个从产生到死亡的过程。 生命周期的五种状态 新建(new Thread) 当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动) 例如:Thread t1=new Thread(); 就绪(runnable) 线程已经被启动,正在...

Formor_的博客 468

取自文库的面试总结

参考地址:https://wenku.baidu.com/view/fe54feadbb0d4a7302768e9951e79b8969026844 java面试参考:https://www.cnblogs.com/jianmang/category/716009.html IOC(控制反...

chuochuanyan9632的博客 83

Java多线程面试题汇总

Java多线程面试题汇总

weixin_42173947的博客 1340

Java 面试题大全 ,吊打面试官

进大厂是大部分程序员的梦想,而进大厂的门槛也是比较高的,所以这里整理了一份阿里、美团、滴滴、头条等大厂面试大全,其中概括的知识点有:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、Spring Boot、Spring Cloud、RabbitMQ、Kafka、Linux 等技术栈。39、你的系统目前有许多正在运行的任务,在不重启机器的条件下,有什么方法可以把所有正在运行的进程移除呢?1、绝对路径用什么符号表示?.

zhaohuodian的博客 447

操作系统专业课复习

一.操作系统概述 操作系统的四个特性 并发:同一段时间内多个程序执行(注意区别并行和并发,前者是同一时刻的多个事件,后者是同一时间段内的多个事件) 共享:系统中的资源可以被内存中多个并发执行的进线程共同使用 虚拟:通过时分复用(如多道程序技术,分时系统)以及空分复用(如虚拟内存)技术实现把一个物理实体虚拟为多个 异步:系统中的进程是以走走停停的方式执行的,且以一种不可预知的速度推进 操作系统的主要...

qq_34866917的博客 559
下一篇: 深入理解JDBC及其超时机制
Foxir
博客等级 码龄12年 1粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值