Files
interview/questions/05-并发编程/Java并发编程基础.md
yasinshaw 0e46a367c4 refactor: rename files to Chinese and organize by category
Organized 50 interview questions into 12 categories:
- 01-分布式系统 (9 files): 分布式事务, 分布式锁, 一致性哈希, CAP理论, etc.
- 02-数据库 (2 files): MySQL索引优化, MyBatis核心原理
- 03-缓存 (5 files): Redis数据结构, 缓存问题, LRU算法, etc.
- 04-消息队列 (1 file): RocketMQ/Kafka
- 05-并发编程 (4 files): 线程池, 设计模式, 限流策略, etc.
- 06-JVM (1 file): JVM和垃圾回收
- 07-系统设计 (8 files): 秒杀系统, 短链接, IM, Feed流, etc.
- 08-算法与数据结构 (4 files): B+树, 红黑树, 跳表, 时间轮
- 09-网络与安全 (3 files): TCP/IP, 加密安全, 性能优化
- 10-中间件 (4 files): Spring Boot, Nacos, Dubbo, Nginx
- 11-运维 (4 files): Kubernetes, CI/CD, Docker, 可观测性
- 12-面试技巧 (1 file): 面试技巧和职业规划

All files renamed to Chinese for better accessibility and
organized into categorized folders for easier navigation.

Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-03-01 00:10:53 +08:00

209 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Java 并发编程基础
## 问题
1. 进程和线程的区别?
2. 创建线程有哪些方式?
3. synchronized 关键字的原理?
4. volatile 关键字的作用?
5. CASCompare And Swap的原理和 ABA 问题?
6. ThreadLocal 的原理和内存泄漏问题?
---
## 标准答案
### 1. 进程 vs 线程
| 特性 | 进程 | 线程 |
|------|------|------|
| **资源** | 独立内存、文件描述符 | 共享进程资源 |
| **通信** | IPC管道、消息队列、共享内存 | 共享内存 |
| **上下文切换** | 慢(需保存更多状态) | 快 |
| **开销** | 大 | 小 |
---
### 2. 创建线程的方式
**方式 1继承 Thread**
```java
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread running");
}
}
new MyThread().start();
```
**方式 2实现 Runnable**
```java
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable running");
}
}
new Thread(new MyRunnable()).start();
```
**方式 3实现 Callable有返回值**
```java
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "Callable result";
}
}
FutureTask<String> future = new FutureTask<>(new MyCallable());
new Thread(future).start();
String result = future.get();
```
---
### 3. synchronized 原理
**字节码层面**
```java
// 同步方法
public synchronized void method() { }
// 字节码ACC_SYNCHRONIZED
// 同步代码块
synchronized (object) { }
// 字节码monitorenter、monitorexit
```
**对象头**
```
Mark Word32 位 JVM
┌────────────┬────────────┬──────────────┐
│ 锁状态 │ 29 位或2位 │ 是否是偏向锁 │
├────────────┼────────────┼──────────────┤
│ 无锁 │ 对象 Hash │ 01 │
│ 偏向锁 │ 线程 ID │ 01 │
│ 轻量级锁 │ 栈中 Lock Record | 00 │
│ 重量级锁 │ 管程指针 │ 10 │
└────────────┴────────────┴──────────────┘
```
**锁升级**
```
无锁 → 偏向锁 → 轻量级锁CAS 自旋) → 重量级锁(阻塞)
```
---
### 4. volatile 关键字
**作用**
1. **保证可见性**JMM主内存与工作内存
2. **禁止指令重排序**
**示例**
```java
private volatile boolean running = true;
public void stop() {
running = false; // 立即对所有线程可见
}
```
**不能保证原子性**
```java
private volatile int count = 0;
// ❌ 非线程安全
count++; // read → modify → write非原子操作
// ✅ 线程安全
synchronized (this) {
count++;
}
```
---
### 5. CAS 和 ABA 问题
**CASCompare And Swap**
```java
// Unsafe.compareAndSwapInt(object, offset, expect, update)
// 如果当前值 == 期望值,则更新为 update
AtomicInteger atomic = new AtomicInteger(0);
atomic.compareAndSet(0, 1); // CAS 操作
```
**ABA 问题**
```
线程 A读取值 A
线程 BA → B → A
线程 ACAS 成功(不知道值已变化)
```
**解决版本号AtomicStampedReference**
```java
AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(100, 0);
int oldStamp = ref.getStamp();
ref.compareAndSet(100, 101, oldStamp, oldStamp + 1); // 版本号也参与 CAS
```
---
### 6. ThreadLocal
**原理**
```java
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = t.threadLocals;
if (map != null)
map.set(this, value); // key 是 ThreadLocal 对象value 是值
else
createMap(t, value);
}
```
**内存泄漏**
```java
// ❌ 可能导致内存泄漏
private static ThreadLocal<byte[]> data = new ThreadLocal<>();
public void process() {
data.set(new byte[1024 * 1024]); // 1MB
// 未调用 remove()
}
```
**原因**
- ThreadLocal 是弱引用,但 value 是强引用
- 线程不销毁value 不会回收
**解决**
```java
try {
data.set(new byte[1024 * 1024]);
// 业务逻辑
} finally {
data.remove(); // 必须
}
```
---
### 7. 阿里 P7 加分项
**深度理解**
- 理解 JMMJava 内存模型)
- 理解 happens-before 原则
- 理解 synchronized 的优化(偏向锁、轻量级锁)
**实战经验**
- 有并发问题的排查经验
- 有性能优化经验(减少锁竞争)
- 有死锁的排查和解决经验