Java中的「Synchronized」:它是什么及如何通过示例工作

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

"synchronized 是什么意思?"——一个困扰着无数初学者的经典问题

\n\n

如果你曾经用 Java 写过多线程应用程序,很可能遇到过这种情况:两个线程同时修改同一个变量,导致 Bug 在运行一百次后才重现一次。听起来熟悉吗?这正是 synchronized 关键字的作用。但它到底做了什么?"底层"是如何工作的?最重要的是——什么时候该使用它,什么时候最好避免使用?

\n\n

在本文中,我们不会只是复述文档。我们将解读一个热门的 Stack Overflow 问题(一个吸引了数千次浏览的问题),将其改编成教学形式,并展示不同方法的对比:方法级同步、块级同步,以及来自 java.util.concurrent 的替代方案。让我们开始吧!

\n\n

问题:竞态条件

\n\n

想象一下:你有一个计数器,由两个线程递增。代码很简单,但结果却出乎意料。

\n\n
public class Counter {\n    private int count = 0;\n\n    public void increment() {\n        count++;\n    }\n\n    public int getCount() {\n        return count;\n    }\n}
\n\n

我们运行两个线程,每个执行 1000 次递增。你期望结果是 2000。但实际上可能是 1987、1993,甚至 1765。为什么?因为 count++ 操作不是原子性的。它由三步组成:读取 → 递增 → 写入。线程"重叠"在一起,导致一个更改丢失了。

\n\n

这就是竞态条件。而 synchronized 是对抗它的主要工具之一。

\n\n

synchronized 做了什么?让我们看看底层

\n\n

Java 中的 synchronized 关键字保证了互斥访问(互斥锁)以及线程之间变更的可见性。当一个线程进入一个 synchronized 块时,它会获取对象(或类)的监视器。其他试图进入同一监视器上任何 synchronized 块的线程将被阻塞,直到该监视器被释放。

\n\n

重要提示:synchronized 只与一个监视器配合工作。如果你有两个不同的对象——同步将不起作用。

\n\n

两种同步级别

\n
    \n
  • 同步方法——锁定整个方法,使用对象自身的监视器(this)。
  • \n
  • 同步块——只锁定部分代码,你可以指定任何对象作为监视器。
  • \n
\n\n

让我们在实践中比较它们。

\n\n

方法对比:方法级 vs 块级

\n\n

1. 同步方法

\n\n

最简单的方法——在方法签名中添加 synchronized。

\n\n
public class SafeCounter {\n    private int count = 0;\n\n    public synchronized void increment() {\n        count++;\n    }\n\n    public synchronized int getCount() {\n        return count;\n    }\n}
\n\n

优点:

\n
    \n
  • 代码量最小,易于阅读。
  • \n
  • 保证整个方法是一个原子操作。
  • \n
\n\n

缺点:

\n
    \n
  • 锁的"重量"很大——即使方法只有一行代码,线程在整个执行期间都会被阻塞。
  • \n
  • 如果方法很长或调用频繁,会降低性能。
  • \n
  • 不够灵活——你无法只同步部分逻辑。
  • \n
\n\n

2. 同步块

\n\n

更细粒度的控制。你可以决定将哪个对象用作监视器。

\n\n
public class SafeCounterWithBlock {\n    private int count = 0;\n    private final Object lock = new Object();\n\n    public void increment() {\n        synchronized (lock) {\n            count++;\n        }\n    }\n\n    public int getCount() {\n        synchronized (lock) {\n            return count;\n        }\n    }\n}

博客

书籍推荐