编程Java 中级/后端开发者

您对 Java 中线程的工作有何了解,以及如何组织线程安全?

用 Hintsage AI 助手通过面试

答复。

在 Java 中,线程的工作通过 ThreadRunnable 类以及 java.util.concurrent 包实现。为了组织线程安全,使用各种同步机制:

  • 同步块/方法 (synchronized) 允许多个线程访问共享数据而不会发生竞态。
  • volatile 确保线程之间对变量更改的可见性。
  • java.util.concurrent 包中的类(例如 ReentrantLockSemaphoreAtomicIntegerConcurrentHashMap)提供了更灵活的同步方式。

同步示例:

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

使用原子类的示例:

import java.util.concurrent.atomic.AtomicInteger; public class AtomicCounter { private AtomicInteger count = new AtomicInteger(0); public void increment() { count.incrementAndGet(); } public int getCount() { return count.get(); } }

考验问题。

关键字 volatile 是否保证在 int 类型计数器递增时的线程安全?

答复: 不。volatile 只确保线程之间的值可见性,而不保证操作的原子性。递增不是原子操作(count++ 包含读取、增加和写入),因此可能会丢失数据。为了获得线程安全的递增,需要同步或像 AtomicInteger 这样的类。

volatile int count = 0; // count++ 不是线程安全的!

因不懂该主题的细微差别而造成的实际错误示例。


故事

在在线商店中,奖金账户通过 volatile 计数器进行更新。在负载下,成千上万的用户下单,部分奖金因对 count++ 的竞态条件而丢失。


故事

员工在多线程应用中使用普通的 ArrayList 作为生产者与消费者之间的共享缓冲区,导致 ConcurrentModificationException。解决方案是使用同步块或替换为 CopyOnWriteArrayList。


故事

在支付处理中,开发者通过两个无关的方法进行“检查并扣款”操作。在高负载条件下,这导致了双重收费,直到引入了原子事务和锁。