ReentrantLock/内存溢出监控
JVM
内存溢出
- 内存泄漏
- 在 java 中如果不再使用一个对象,但是该对象依然在 GC ROOT 引用链尚,这个对象就不会被垃圾回收器回收,这种情况就成为内存泄露
- 内存溢出
- 当持续发生内存泄漏直到内存被消耗完就会导致内存溢出
监控工具
- Top 命令
- top 命令是 linux 下用来查看系统信息的一个命令,它提供给我们去实时地去查看系统的资源,比如执行时的进程、线程和系统参数等信息。进程使用的内存为 RES(常驻内存)SHR(共享内存)
- VisualVM
- VisualVM 是多功能合一的 Java 故障排除工具并且他是一款可视化工具,整合了命令行 JDK 工具和轻量级分析功能,功能非常强大。这款软件在 Oracle JDK 6~8 中发布,但是在 Oracle JDK 9 之后不在 JDK 安装目录下需要单独下载
- Arthas
- Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。
产生内存溢出的原因
- 代码中的内存泄露
-
equals() 和 hashCode(),不正确的 equals() 和 hashCode() 实现导致内存泄漏
-
ThreadLocal 的使用,由于线程池中的线程不被回收导致的 ThreadLocal 内存泄漏
-
内部类引用外部类,非静态的内部类和匿名内部类的错误使用导致内存泄漏
-
String 的 intern 方法,由于 JDK6 中的字符串常量池位于永久代,intern 被大量调用并保存产生的内存泄漏
-
通过静态字段保存对象,大量的数据在静态变量中被引用,但是不再使用,成为了内存泄漏
-
资源没有正常关闭,由于资源没有调用 close 方法正常关闭,导致的内存溢出
-
- 并发请求问题
- 并发请求问题指的是由于用户的并发请求量有可能很大,同时处理数据的时间很长,导致大量的数据存在于内存中,最终超过了内存的上限,导致内存溢出。这类问题的处理思路和内存泄漏类似,首先要定位到对象产生的根源。
JUC
ReentrantLock
- 可重入
- 可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁
- 如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住
- 可打断
- 锁超时
- 公平锁
- ReentrantLock 默认是不公平的
- 公平锁一般没有必要,会降低并发度
- 条件变量
- synchronized 中也有条件变量,就是我们讲原理时那个 waitSet 休息室,当条件不满足时进入 waitSet 等待
- ReentrantLock 的条件变量比 synchronized 强大之处在于,它是支持多个条件变量的,这就好比
- synchronized 是那些不满足条件的线程都在一间休息室等消息 而
- ReentrantLock 支持多间休息室,有专门等烟的休息室、专门等早餐的休息室、唤醒时也是按休息室来唤 醒
- 使用要点:await 前需要获得锁 await 执行后,会释放锁,进入 conditionObject 等待 await 的线程被唤醒(或打断、或超时)取重新竞争 lock 锁 竞争 lock 锁成功后,从 await 后继续执行