在 Java 中,线程的工作通过 Thread、Runnable 类以及 java.util.concurrent 包实现。为了组织线程安全,使用各种同步机制:
synchronized) 允许多个线程访问共享数据而不会发生竞态。ReentrantLock、Semaphore、AtomicInteger、ConcurrentHashMap)提供了更灵活的同步方式。同步示例:
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。
故事
在支付处理中,开发者通过两个无关的方法进行“检查并扣款”操作。在高负载条件下,这导致了双重收费,直到引入了原子事务和锁。