BufferedInputStream 的 lock 域是内置同步锚点,非显式锁对象,其值为 this,仅用于 synchronized 块的监视器;所有 public 方法共用该锁,粒度粗、不可定制,高并发下易成瓶颈,优化应避免共享实例或改用 NIO。

BufferedInputStream 的 lock 域本身不是用于显式加锁的“锁对象”,而是一个供 synchronized 语句内部使用的同步锚点——它本质上是该类为保证线程安全而内置的、默认指向 this 的引用(在 JDK 8+ 中实际被初始化为 this),其作用仅限于同步块的锁目标,不提供 Lock 接口能力,也不参与 ReentrantLock 等显式锁逻辑。
lock 域的真实角色
BufferedInputStream 继承自 FilterInputStream,其所有 public 方法(如 read()、skip()、available())都被 synchronized 修饰,底层统一使用 lock 字段作为同步监视器(monitor)。源码中类似:
public int read() throws IOException {
synchronized (lock) {
// 实际读取逻辑
}
}
这意味着:每次调用都会进入以 lock 为锁对象的同步块,而非直接锁住整个实例(尽管效果常等价,因 lock == this)。
性能影响的关键点
- 锁粒度固定且较粗:所有 I/O 操作共用同一把锁,即使只读不写、或多个线程读不同位置,也会相互阻塞。高并发下易成瓶颈
- 无法规避的同步开销:每次方法调用都触发 monitor enter/exit,涉及 JVM 锁机制(偏向锁→轻量级锁→重量级锁)的判断与可能的系统态切换
-
lock 域不可替换或定制:它是 private final 字段,用户不能重新赋值或传入外部锁对象,丧失了
synchronized(obj)的灵活性 -
与显式 Lock 无关联:ReentrantLock 等不会、也不能作用于这个
lock域;它只是 synchronized 的载体,不实现任何 Lock 接口
实际优化建议
- 避免多线程共享单个 BufferedInputStream 实例:每个线程应持有独立实例,消除锁争用。这是最直接有效的做法
-
大吞吐场景优先考虑 NIO:用
FileChannel+ByteBuffer替代流式读取,绕过 synchronized 机制,支持零拷贝和异步操作 - 若必须用 BufferedInputStream,合理设置缓冲区大小:8KB–64KB 范围内根据数据源调整,减少系统调用频次,摊薄同步成本
-
不要试图“包装” lock 域做细粒度控制:它不是设计用来被外部 synchronized 块嵌套使用的字段,强行用
synchronized(bufIn.lock)不仅冗余,还可能引入死锁风险(尤其与内部同步叠加时)
本质上,BufferedInputStream 的 lock 域是 Java IO 包为向后兼容而保留的线程安全机制,它的存在意义在于简化单线程或低并发使用,而非支撑高性能并发。真有高并发 IO 需求,应跳出流模型,转向 NIO 或异步框架。
立即学习“Java免费学习笔记(深入)”;



















