知用网
霓虹主题四 · 更硬核的阅读氛围

线程安全与并发的区别:别再傻傻分不清

发布时间:2025-12-14 21:20:41 阅读:136 次

很多人在写多线程程序时,常把“线程安全”和“并发”混为一谈。比如你开了个奶茶店小程序,两个顾客同时下单,结果库存减成了负数——这时候你可能会说:‘这不就是并发出的问题吗?’ 没错,但更准确地说,是你的代码不支持线程安全

并发是场景,线程安全是能力

并发指的是多个任务在同一时间段内交替执行,比如系统同时处理多个用户请求。它描述的是一种运行状态,就像早高峰地铁站里人挤人,大家都在同一时间赶着进站。

而线程安全是指一段代码在被多个线程同时访问时,依然能保持正确的行为。就像地铁闸机,哪怕一百个人同时刷卡,它也能准确记录每个人进出,不会多扣钱也不会漏算。这就是线程安全的表现。

举个例子:银行取款机

假设两个人共用一张卡,同时在不同ATM上查余额并取钱。如果系统没有做线程安全控制,可能出现两人同时看到余额5000元,接着都取走3000元,最终账户变成-1000元。

问题不在“并发”本身——我们当然希望系统能同时服务多个操作。问题在于共享数据(余额)被多个线程修改时,缺乏保护机制。这时候你需要的是线程安全的实现方式,比如加锁。

代码对比更清楚

下面是一个非线程安全的计数器:

public class Counter {
    private int count = 0;

    public void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

看似简单,但在高并发环境下,多个线程同时执行 count++,这个操作其实包含读、改、写三步,可能互相覆盖,导致最终结果不准。

改成线程安全版本:

public class SafeCounter {
    private int count = 0;
    private final Object lock = new Object();

    public void increment() {
        synchronized(lock) {
            count++;
        }
    }

    public int getCount() {
        synchronized(lock) {
            return count;
        }
    }
}

加上了同步锁,确保同一时间只有一个线程能进入关键区域。这时候即使并发量再大,结果也是可靠的。

不是所有并发都需要线程安全

如果每个线程操作的是自己的数据,比如每个用户独立会话、各自购物车,彼此不共享状态,那根本不需要考虑线程安全。并发照样跑得飞快,还省去了锁的开销。

换句话说,并发关注的是“能不能一起干”,线程安全关心的是“一起干会不会乱”。一个是并行的规模,一个是共享资源的防护。

现代开发中的常见做法

现在很多人用 ConcurrentHashMap 而不是 HashMap,用 AtomicInteger 替代普通 int 计数,就是为了在高并发场景下保证线程安全。这些类底层已经做好了同步处理,开发者不用从头造轮子。

另外,函数式编程提倡不可变对象(immutable),也是为了避开线程安全问题。一个对象创建后就不能改,大家只读不写,自然不怕冲突。

理解这一点,你在设计系统时就会更有分寸:不是一上来就加锁,而是先看有没有共享可变状态。没有共享,就不需要安全;有并发需求,才考虑如何安全地并发。