并发编程详解
线程创建与生命周期
- 创建方式:继承 Thread 重写 run;实现 Runnable 传 Thread;实现 Callable 配 FutureTask。推荐 Runnable/Callable,便于线程池与复用。
- 状态:NEW、RUNNABLE(含就绪与运行)、BLOCKED(等 monitor)、WAITING(无时限 wait/join)、TIMED_WAITING(sleep/带时限 wait)、TERMINATED。
- start() 只能调用一次;run() 只是普通方法,直接调用不会新线程。
synchronized
- 用法:修饰实例方法(锁 this)、静态方法(锁 Class)、代码块 synchronized(obj)。同一锁同一时刻仅一线程持有;可重入。
- 原理:Monitor(管程);字节码 monitorenter/monitorexit;锁存在对象头 Mark Word。
- 锁升级:无锁 → 偏向锁(单线程多次进入)→ 轻量级锁(CAS 自旋)→ 重量级锁(挂起,OS 互斥)。-XX:-UseBiasedLocking 可关偏向锁。
Lock 与 ReentrantLock
- 显式加锁解锁;unlock 必须在 finally。可重入;公平/非公平(默认);tryLock()、lockInterruptibly()。
- 与 synchronized 区别:Lock 可非块结构、可中断、可超时、多条件;synchronized 由 JVM 实现,自动释放。
volatile
- 保证可见性:写立即刷新主存,读从主存读(或缓存一致性协议)。禁止指令重排:内存屏障。
- 不保证原子性;适合一写多读、状态标志。i++ 等需 CAS 或 synchronized。
CAS
- Compare-And-Swap;无锁更新,ABA 问题可用版本号或 AtomicStampedReference 解决。
- AtomicInteger、AtomicLong、AtomicReference、LongAdder(高并发计数拆分 cell,再 sum)。
AQS(AbstractQueuedSynchronizer)
- state 表示资源数;CLH 队列管理等待线程。获取:tryAcquire 成功则占坑,失败则入队、挂起;释放:tryRelease 改 state,唤醒后继。
- 基于 AQS:ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch(共享)、CyclicBarrier 通过 ReentrantLock+Condition 实现。
JMM(Java 内存模型)
- 主内存与工作内存;线程对变量的操作在工作内存,再同步到主内存。happens-before:程序顺序、锁规则、volatile、传递性等;满足 hb 则可见性有保障。
- volatile、synchronized、final 的可见性与有序性保证。
线程池
参数
- corePoolSize:核心线程数,常驻。
- maximumPoolSize:最大线程数。
- keepAliveTime + unit:非核心线程空闲存活时间。
- workQueue:任务队列,ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue、DelayedWorkQueue 等。
- threadFactory:创建线程的工厂。
- handler:拒绝策略;AbortPolicy(抛异常)、CallerRunsPolicy(调用者跑)、DiscardPolicy、DiscardOldestPolicy。
流程
- 任务数 ≤ corePoolSize:新建核心线程执行。
- 任务数 > corePoolSize:放入 workQueue。
- 队列满且 当前线程数 < maximumPoolSize:新建非核心线程。
- 队列满且 当前线程数 = maximumPoolSize:执行 handler。
为什么不用 Executors
- newFixedThreadPool、newSingleThreadExecutor 用无界 LinkedBlockingQueue,任务堆积可能 OOM。
- newCachedThreadPool 最大线程数为 Integer.MAX_VALUE,可能创建过多线程。推荐手动 new ThreadPoolExecutor,显式设队列大小与拒绝策略。
线程池参数设计
- CPU 密集:核心数 + 1 或 Ncpu;IO 密集:可 2*Ncpu 或按 IO 等待比放大。队列有界;拒绝策略按业务选(记录、降级、CallerRunsPolicy)。
CompletableFuture
- 组合异步任务;supplyAsync、thenApply、thenCompose、thenCombine、allOf、anyOf、exceptionally、handle。
- 替代 Future.get() 阻塞;可链式编排多步异步。
ConcurrentHashMap
- JDK8:CAS + synchronized 锁桶;put/get 见 集合。size 用 baseCount + CounterCell 分段计数。
并发工具类
- CountDownLatch:计数减到 0 时 await 的线程放行;一次性。countDown()、await()。
- CyclicBarrier:多线程到齐后执行屏障动作;可复用。await()。
- Semaphore:许可数,acquire/release;限流、控制并发数。
- Phaser:分阶段协同,可动态注册。
- ThreadLocal:线程局部变量;注意内存泄漏:用完 remove(),或使用池化线程时务必 remove。
必会问题简答
- volatile 的作用:可见性、禁止重排;不保证原子性。
- synchronized 和 Lock 区别:见上 Lock 小节。
- 线程池参数怎么设计:见上「线程池参数设计」。