线程安全的类 ≠ 线程安全的程序

java 复制代码
import java.util.Vector;

public class Demo20 {
    public static void main(String[] args) throws InterruptedException {
        Vector<String> v = new Vector<>();
        Thread t1 = new Thread(() -> {
            if(v.isEmpty()) {
                v.add("hello");
            }
        });

        Thread t2 = new Thread(() -> {
            if(v.isEmpty()) {
                v.add("hello");
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(v);
    }
}

假设你修复了 join() 问题,现在考虑这个逻辑:

java 复制代码
if (v.isEmpty()) {   // ← 检查
   v.add("hello");  // ← 操作
}

虽然 isEmpty()add() 各自是线程安全的(Vector 内部加锁),但这两个操作合起来不是原子的

🧨 并发执行时的可能场景:
时间 线程 t1 线程 t2
t1 调用 v.isEmpty() → 返回 true ---
t2 --- 调用 v.isEmpty() → 返回 true
t3 执行 v.add("hello") ---
t4 --- 执行 v.add("hello")

→ 最终 v = ["hello", "hello"]

❌ 这违反了"只添加一次"的意图!

这就是 "复合操作非原子" 的经典问题。

✅ 为什么 Vector 的线程安全不够用?

  • Vector 保证的是:单个方法调用是原子的 (如 add()isEmpty()get() 等)。

  • 但它无法保证多个方法调用之间的逻辑是原子的

  • 这种"先判断再操作"的模式,需要外部同步

✅ 正确解决方案:对外层逻辑加锁(推荐)

java 复制代码
public class Demo20 {
    public static void main(String[] args) throws InterruptedException {
        Vector<String> v = new Vector<>();
        
        Thread t1 = new Thread(() -> {
            synchronized (v) { // 使用 Vector 自身作为锁
                if (v.isEmpty()) {
                    v.add("hello");
                }
            }
        });

        Thread t2 = new Thread(() -> {
            synchronized (v) {
                if (v.isEmpty()) {
                    v.add("hello");
                }
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        
        System.out.println(v); // 输出: [hello] (只添加一次)
    }
}

✅ 因为 Vector 本身用 this 加锁,所以我们也可以用 synchronized(v) 来保护复合操作。

相关推荐
天若有情67337 分钟前
程序员原创|借鉴JS事件冒泡,根治电脑文件混乱的“冒泡整理法”
开发语言·javascript·windows·ecmascript·电脑·办公·日常
qq_5895681041 分钟前
springbootweb案例,出现访问 http://localhost:8080/list 一直处于浏览器运转阶段
java·网络协议·http·list·springboot
JAVA面经实录9171 小时前
计算机基础(完整版·超详细可背诵)
java·linux·数据结构·算法
特种加菲猫1 小时前
继承,一场跨越时空的对话
开发语言·c++
AC赳赳老秦1 小时前
知识产权辅助:用 OpenClaw 批量生成专利交底书 / 软著申请材料,自动校验格式与内容合规性
java·人工智能·python·算法·elasticsearch·deepseek·openclaw
FYKJ_20102 小时前
springboot校园兼职平台--附源码02041
java·javascript·spring boot·python·eclipse·django·php
玩转单片机与嵌入式2 小时前
玩转边缘AI(TInyML):需要掌握的C++知识汇总!
开发语言·c++·人工智能
茉莉玫瑰花茶3 小时前
Qt 信号与槽 [ 1 ]
开发语言·数据库·qt
书源丶3 小时前
三十六、File 类与 IO 流基础——文件操作的「第一步」
java