java synchronized 的粗粒度锁主要问题是并发度低,导致线程竞争加剧、吞吐量下降和响应延迟增加。具体做法是将锁的范围缩小到只保护共享数据的最小代码块,或者使用更细粒度的锁机制如 reentrantreadwritelock 或 concurrenthashmap,从而减少线程阻塞时间并提高系统整体性能。

synchronized 在方法级别加锁会导致什么后果
当 synchronized 修饰整个方法时,任何调用该方法的线程都会获取对象锁,即使方法内部大部分代码是无关的。这会导致非共享资源的访问也被强制串行化,造成不必要的等待。例如,一个包含大量 I/O 操作或纯计算逻辑的方法,如果全部被锁住,其他线程必须等待整个方法执行完毕才能进入,显著降低并发能力。

public class Counter {
private int count = 0;
// 粗粒度锁:整个方法被锁定
public synchronized void increment() {
// 模拟耗时操作,如日志记录或网络请求
try { Thread.sleep(10); } catch (InterruptedException e) {}
count++;
}
public synchronized int getCount() {
return count;
}
}
上述代码中,increment 和 getCount 都使用了 synchronized。这意味着即使只是读取 count,线程也必须等待其他线程释放锁。如果 increment 中有耗时操作,getCount 也会被阻塞,导致读操作无法并发执行。
如何优化 synchronized 的锁粒度
优化方案是将 synchronized 块限制在仅修改共享变量的最小范围,避免包裹无关逻辑。对于读多写少的场景,可考虑使用 ReentrantReadWriteLock 分离读写锁;对于集合类,优先使用 ConcurrentHashMap 等并发工具。这样可以让读操作并行执行,写操作串行执行,最大化并发效率。
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型

public class OptimizedCounter {
private int count = 0;
public void increment() {
// 模拟耗时操作,不在锁内
try { Thread.sleep(10); } catch (InterruptedException e) {}
synchronized (this) {
count++;
}
}
public int getCount() {
synchronized (this) {
return count;
}
}
}
在 OptimizedCounter 中,只有 count++ 和 return count 被同步,耗时操作在锁外执行。这样多个线程可以同时执行 increment 中的耗时部分,仅在更新计数时竞争锁,大幅提升了并发吞吐量。
基于程序中某个输入、条件或结果的具体问题
在上述 OptimizedCounter 中,如果多线程同时调用 increment,count 的值是否正确?答案是正确的,因为 synchronized 保证了原子性。但如果改为使用 volatile int count 而不加锁,则会出现竞态条件,导致 count 值不准确。因此,对于复合操作(如 read-modify-write),必须使用锁或原子类来保证一致性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










