Java并发编程:血泪教训与八大神器

编程达人挑战赛·第5期 10w+人浏览 166人参与

一、血泪教训:那些让你头皮发麻的并发Bug现场

场景1:简单的计数器,不简单的灾难

// 你以为安全的计数器?
public class Counter {
    private int count = 0;
    
    public void increment() {
        count++;  // 致命!这不是原子操作
    }
    
    public int getCount() {
        return count;
    }
}

// 在多线程环境下,100个线程各执行1000次increment()
// 你期望的结果:100000
// 实际结果可能是:97843、99217...每次都不一样!

场景2:Spring单例Bean中的“陷阱”

@Service
public class OrderService {
    // 单例Bean中的成员变量 - 线程安全大坑!
    private Map<Long, Order> currentOrders = new HashMap<>();
    
    public void processOrder(Long orderId) {
        Order order = orderDao.findById(orderId);
        currentOrders.put(orderId, order);  // 多个线程并发操作同一个Map!
        // ... 业务处理
        currentOrders.remove(orderId);
    }
}

场景3:SimpleDateFormat引发的午夜惊魂

// 全局共享的日期格式化器 - 经典错误
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

public String formatDate(Date date) {
    return sdf.format(date);  // 多线程下可能返回乱码或抛出异常!
}

// 真实案例:某银行系统在月末对账时出现日期错乱,损失惨重

二、深度剖析:为什么线程安全如此棘手?

根源分析

  1. 可见性问题:一个线程的修改,另一个线程看不见

  2. 原子性问题:看似一行代码,实际包含多个操作

  3. 有序性问题:编译器/处理器重排序导致的诡异现象

JMM(Java内存模型)真相

// 看似简单的代码,隐藏着内存可见性问题
public class VisibilityProblem {
    private boolean flag = false;  // 问题所在!
    private int value = 0;
    
    public void writer() {
        value = 42;
        flag = true;  // 在另一个线程中,可能先看到这行!
    }
    
    public void reader() {
        if (flag) {
            // value可能看到0,而不是42!
            System.out.println("Value: " + value);
        }
    }
}

并发三要素的具象化

// 1. 原子性破坏示例
i++;  // 实际是:读取i → 计算i+1 → 写入i

// 2. 可见性破坏示例
// 线程A修改了共享变量,线程B却看到了旧值

// 3. 有序性破坏示例
// 指令重排导致初始化未完成就被使用

三、八大神器:构建线程安全的铜墙铁壁

神器1:synchronized - 最经典的解决方案

// 正确使用synchronized的姿势
public class SafeCounter {
    private int count = 0;
    private final Object lock = new Object();  // 专用锁对象
    
    // 方法1:同步方法
    public synchronized void increment() {
        count++;
    }
    
    // 方法2:同步块(更细粒度控制)
    public void safeIncrement() {
        synchronized (lock) {
            count++;
        }
    }
    
    // 双重检查锁定的正确实现(单例模式)
    public class Singleton {
        private static volatile Singleton instance;  // 必须volatile!
        
        public static Singleton getInstance() {
            if (instance == null) {  // 第一次检查
                synchronized (Singleton.class) {
                    if (instance == null) {  // 第二次检查
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
}

神器2:Atomic家族 - 无锁并发利器

import java.util.concurrent.atomic.*;

public class AtomicDemo {
    // 原子整数
    private AtomicInteger counter = new AtomicInteger(0);
    
    // 原子引用
    private AtomicReference<User> userRef = new AtomicReference<>();
    
    // 原子数组
    private AtomicIntegerArray array = new AtomicIntegerArray(10);
    
    // 累加器(更高性能的统计)
    private LongAdder adder = new LongAdder();  // JDK8+
    
    public void demo() {
        // CAS操作
        int oldValue, newValue;
        do {
            oldValue = counter.get();
            newValue = oldValue + 1;
        } while (!counter.compareAndSet(oldValue, newValue));
        
        // 简化API
        counter.incrementAndGet();
        adder.increment();
        
        // 原子更新复杂对象
        User oldUser, newUser;
        do {
            oldUser = userRef.get();
            newUser = updateUser(oldUser);
        } while (!userRef.compareAndSet(oldUser, newUser));
    }
}

神器3:Concurrent集合 - 高性能线程安全容器

public class ConcurrentCollectionDemo {
    // 1. ConcurrentHashMap - 分段锁实现
    private ConcurrentHashMap<String, Object> cache = new ConcurrentHashMap<>();
    
    public void safeCacheOperation() {
        // 线程安全的putIfAbsent
        cache.putIfAbsent("key", computeExpensiveValue());
        
        // 并发安全的遍历
        cache.forEach((k, v) -> process(k, v));
        
        // 原子更新
        cache.compute("key", (k, v) -> v == null ? 1 : (Integer)v + 1);
    }
    
    // 2. CopyOnWriteArrayList - 读多写少场景
    private CopyOnWriteArrayList<String> logList = new CopyOnWriteArrayList<>();
    
    public void logOperation() {
        // 写时复制,读操作完全无锁
        logList.add("new log");  // 每次add都会复制内部数组
        
        // 适合监听器列表等场景
        for (String log : logList) {  // 遍历的是快照,线程安全
            processLog(log);
        }
    }
    
    // 3. ConcurrentLinkedQueue - 高性能队列
    private ConcurrentLinkedQueue<Task> taskQueue = new ConcurrentLinkedQueue<>();
    
    // 4. BlockingQueue - 生产者消费者模式
    private BlockingQueue<Message> messageQueue = new LinkedBlockingQueue<>(1000);
}

神器4:ThreadLocal - 线程私有变量

// ThreadLocal的正确使用姿势
public class ThreadLocalDemo {
    // 1. SimpleDateFormat的安全用法
    private static final ThreadLocal<SimpleDateFormat> dateFormatHolder =
        ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
    
    public String formatDate(Date date) {
        return dateFormatHolder.get().format(date);  // 每个线程有自己的实例
    }
    
    // 2. 用户上下文传递
    public class UserContextHolder {
        private static final ThreadLocal<User> currentUser = new ThreadLocal<>();
        
        public static void set(User user) {
            currentUser.set(user);
        }
        
        public static User get() {
            return currentUser.get();
        }
        
        public static void clear() {
            currentUser.remove();  // 必须清理,防止内存泄漏!
        }
    }
    
    // 3. 数据库连接管理
    public class ConnectionHolder {
        private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<>();
        
        public static Connection getConnection() {
            Connection conn = connectionHolder.get();
            if (conn == null) {
                conn = DataSource.getConnection();
                connectionHolder.set(conn);
            }
            return conn;
        }
        
        public static void close() {
            Connection conn = connectionHolder.get();
            if (conn != null) {
                try { conn.close(); } catch (SQLException e) { /* ignore */ }
                connectionHolder.remove();  // 关键!
            }
        }
    }
}

神器5:Lock框架 - 更灵活的锁控制

import java.util.concurrent.locks.*;

public class LockFrameworkDemo {
    // ReentrantLock - 可重入锁
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    
    public void transfer(Account from, Account to, BigDecimal amount) {
        lock.lock();  // 手动获取锁
        try {
            // 业务逻辑
            from.withdraw(amount);
            to.deposit(amount);
            
            // 条件等待
            while (!conditionSatisfied()) {
                condition.await();  // 释放锁并等待
            }
            
            condition.signalAll();  // 唤醒等待线程
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();  // 必须在finally中释放!
        }
    }
    
    // ReadWriteLock - 读写分离锁
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final Lock readLock = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();
    
    public Object readData(String key) {
        readLock.lock();
        try {
            return cache.get(key);  // 允许多个读线程并发
        } finally {
            readLock.unlock();
        }
    }
    
    public void writeData(String key, Object value) {
        writeLock.lock();
        try {
            cache.put(key, value);  // 只允许一个写线程
        } finally {
            writeLock.unlock();
        }
    }
}

神器6:并发工具类 - JDK的并发武器库

import java.util.concurrent.*;

public class ConcurrentUtilsDemo {
    // 1. CountDownLatch - 多线程等待
    public void batchProcess(List<Task> tasks) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(10);
        CountDownLatch latch = new CountDownLatch(tasks.size());
        
        for (Task task : tasks) {
            executor.submit(() -> {
                try {
                    task.execute();
                } finally {
                    latch.countDown();  // 完成一个任务
                }
            });
        }
        
        latch.await();  // 等待所有任务完成
        System.out.println("所有任务完成!");
    }
    
    // 2. CyclicBarrier - 线程栅栏
    public void multiPhaseCalculation() {
        CyclicBarrier barrier = new CyclicBarrier(3, () -> {
            System.out.println("所有线程完成第一阶段");
        });
        
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                phase1();
                barrier.await();
                phase2();
                barrier.await();
            }).start();
        }
    }
    
    // 3. Semaphore - 信号量(限流)
    public class ConnectionPool {
        private final Semaphore semaphore = new Semaphore(10);  // 最多10个连接
        
        public Connection getConnection() throws InterruptedException {
            semaphore.acquire();  // 获取许可
            return createConnection();
        }
        
        public void releaseConnection(Connection conn) {
            closeConnection(conn);
            semaphore.release();  // 释放许可
        }
    }
    
    // 4. CompletableFuture - 异步编程
    public CompletableFuture<User> getUserAsync(Long userId) {
        return CompletableFuture.supplyAsync(() -> {
            return userDao.findById(userId);  // 异步执行
        }).exceptionally(ex -> {
            log.error("查询用户失败", ex);
            return User.anonymous();
        });
    }
}

神器7:不可变对象 - 最简单的线程安全

// 不可变对象的黄金法则
public final class ImmutableUser {  // 1. final类
    private final Long id;           // 2. final字段
    private final String name;
    private final List<String> roles;  // 3. 引用类型需要特殊处理
    
    // 4. 构造时初始化所有字段
    public ImmutableUser(Long id, String name, List<String> roles) {
        this.id = id;
        this.name = name;
        // 防御性复制
        this.roles = Collections.unmodifiableList(new ArrayList<>(roles));
    }
    
    // 5. 不提供setter方法
    
    // 6. 返回不可变视图
    public List<String> getRoles() {
        return Collections.unmodifiableList(roles);
    }
    
    // 7. 如需修改,返回新对象
    public ImmutableUser withName(String newName) {
        return new ImmutableUser(this.id, newName, this.roles);
    }
}

// 枚举实现单例(线程安全)
public enum Singleton {
    INSTANCE;
    
    public void service() {
        // 线程安全的方法
    }
}

神器8:性能与安全兼备的并发模式

// 模式1:线程封闭(Thread Confinement)
public class ThreadConfinementDemo {
    // 栈封闭 - 局部变量是线程安全的
    public void process() {
        List<String> localList = new ArrayList<>();  // 每个线程有自己的实例
        // 安全操作localList
    }
    
    // ThreadLocal封闭
    private ThreadLocal<SimpleDateFormat> formatHolder = ...;
}

// 模式2:不变性(Immutability)
// 使用不可变对象和不可变集合

// 模式3:保护性复制(Defensive Copy)
public class DefensiveCopyDemo {
    private final List<String> data;
    
    public DefensiveCopyDemo(List<String> input) {
        // 构造时复制
        this.data = new ArrayList<>(input);
    }
    
    public List<String> getData() {
        // 返回时复制
        return new ArrayList<>(data);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值