尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

聊聊Java开发中常见的并发问题与解决方案

聊聊Java开发中常见的并发问题与解决方案 做Java后端开发迟早要面对一个问题代码在本地跑得好好的一上生产、并发一上来各种莫名其妙的问题就冒出来了。数据错乱、线程卡死、CPU飙升……这些问题的根源十有八九都指向了并发编程。根据某电商大促系统的实践数据显示70%的线上故障源于并发控制不当。今天就从实际项目出发聊聊那些最常见的并发问题以及怎么解决。竞态条件你以为的原子操作其实不是最经典的坑莫过于i。很多开发者认为这就是一行代码理所当然应该是原子操作。但实际上它会被拆分成“读取-修改-写入”三个步骤。当多个线程同时执行时线程A读到值还没来得及写线程B已经完成了修改A再写回去就把B的结果覆盖了。解决方案很简单对于简单的计数场景直接用AtomicInteger它通过CASCompare-And-Swap机制保证原子性性能优于重量级的synchronized。如果是统计场景LongAdder通过分段累加减少竞争性能更优。可见性你改的变量别的线程看不见另一个隐蔽的问题是可见性。CPU和内存之间速度差异巨大每个线程可能把共享变量缓存在自己的CPU缓存里。线程A修改了变量只是写到了缓存里还没来得及刷回主内存线程B读取时拿到的还是旧值。有个经典案例能说明问题两个线程分别给a和b赋值同时读取对方的变量结果可能出现x0, y0这种看似不可能的情况——就是因为可见性和指令重排序共同作用的结果。解决方案用volatile关键字修饰共享变量强制线程每次读取都从主内存拿、修改后立即刷回主内存。但要注意volatile只保证可见性不保证原子性——volatile int count配合count依然是不安全的。如果需要同时保证原子性和可见性用synchronized或Atomic类。死锁互相等待谁也别想动死锁是并发编程中最头疼的问题之一。两个线程互相持有对方需要的锁谁也不释放双双卡死。一个典型场景线程A先拿锁1再拿锁2线程B先拿锁2再拿锁1。看起来没什么但并发执行时极可能死锁。解决方案有几个方向统一锁顺序给所有锁资源编号所有线程按编号递增的顺序获取锁从根本上打破“循环等待”。使用定时锁用Lock.tryLock(timeout, unit)代替synchronized获取不到锁就超时放弃避免永久阻塞。减少锁粒度尽量避免嵌套锁能用一把锁解决的绝不用两把。排查工具线上出现死锁用jstack piddump线程快照能看到哪些线程处于BLOCKED状态、在等什么锁。jconsole和jvisualvm也能直观地检测死锁。线程池用错了比不用还危险线程池是控制并发的利器但用错了就是灾难。最典型的问题是用Executors的快捷方法创建线程池。Executors.newFixedThreadPool(n)用的是无界队列LinkedBlockingQueue任务堆积起来会撑爆内存导致OOM。Executors.newCachedThreadPool()最大线程数是Integer.MAX_VALUE并发一高就创建海量线程直接把系统资源耗尽。阿里的Java开发手册明令禁止在生产环境使用Executors创建线程池。正确的做法通过ThreadPoolExecutor的构造函数手动配置所有参数。核心线程数要根据任务类型来定——CPU密集型设为核心数±1IO密集型可以设为核心数的5-10倍。队列必须用有界队列配合拒绝策略处理溢出。并发容器换了ConcurrentHashMap就万事大吉很多人觉得把HashMap换成ConcurrentHashMap就高枕无忧了。但ConcurrentHashMap只保证单个方法的线程安全复合操作依然不安全。比如先get再put两个操作之间可能有其他线程修改了数据。正确做法是用putIfAbsent、compute等原子方法。另外注意ConcurrentHashMap的key和value都不能是null这是为了防止并发场景下的歧义。SimpleDateFormat也是高频踩坑点——它不是线程安全的多个线程共用同一个实例会出乱子。要么每次新建要么用ThreadLocal包装。虚拟线程新工具也有新问题Java 21引入了虚拟线程大幅降低了高并发编程的门槛。但新工具也有新坑——虚拟线程在synchronized块内可能发生pinning导致底层平台线程被占用无法释放。Netflix在生产环境引入虚拟线程时就遇到了超时和服务挂起的问题。好消息是JDK 25已经解决了大部分pinning问题但迁移时仍需谨慎测试。说到底并发编程没有银弹。理解问题的本质——原子性、可见性、有序性——比背一堆解决方案更重要。每次遇到并发问题先问自己是哪个底层原理出了问题搞清楚了解决方案自然就有了。
返回列表