# 并发编程

## 目录
- [并发概念](#并发概念)
- [同步与异步](#同步与异步)
- [锁机制](#锁机制)
- [原子类](#原子类)
- [并发集合](#并发集合)
- [并发编程最佳实践](#并发编程最佳实践)
- [面试常见问题](#面试常见问题)

---

## 并发概念

### 并发 vs 并行

```java
// 并发：同一时间段内多个任务交替执行
// 单核 CPU：时间片轮转

// 并行：同一时刻多个任务同时执行
// 多核 CPU：真正同时执行
```

### 并发问题

```java
// 问题1：竞态条件
private int count = 0;

public void increment() {
    count++; // 非原子操作
    // 1. 读取 count
    // 2. count + 1
    // 3. 写入 count
    // 多线程同时执行可能导致数据错误
}

// 问题2：可见性问题
private boolean flag = false;

// 线程1
flag = true;

// 线程2
while (!flag) {
    // 可能永远循环（可见性问题）
}
```

---

## 同步与异步

### 同步

```java
// 同步：按顺序执行，等待结果
public void syncMethod() {
    String result = loadData(); // 等待加载完成
    updateUI(result);
}
```

### 异步

```java
// 异步：不等待结果，继续执行
public void asyncMethod() {
    loadDataAsync(new Callback() {
        @Override
        public void onResult(String result) {
            updateUI(result);
        }
    });
    // 继续执行其他代码
}
```

---

## 锁机制

### synchronized

```java
// 同步方法
public synchronized void method() {
    // 临界区代码
}

// 同步代码块
public void method() {
    synchronized (this) {
        // 临界区代码
    }
}

// 同步静态方法
public static synchronized void staticMethod() {
    // 临界区代码
}
```

### ReentrantLock

```java
// ReentrantLock：可重入锁
private Lock lock = new ReentrantLock();

public void method() {
    lock.lock();
    try {
        // 临界区代码
    } finally {
        lock.unlock();
    }
}

// 可中断锁
lock.lockInterruptibly();
try {
    // 临界区代码
} finally {
    lock.unlock();
}
```

### ReadWriteLock

```java
// ReadWriteLock：读写锁
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private Lock readLock = readWriteLock.readLock();
private Lock writeLock = readWriteLock.writeLock();

// 读操作
public String read() {
    readLock.lock();
    try {
        return data;
    } finally {
        readLock.unlock();
    }
}

// 写操作
public void write(String value) {
    writeLock.lock();
    try {
        data = value;
    } finally {
        writeLock.unlock();
    }
}
```

---

## 原子类

### AtomicInteger

```java
// AtomicInteger：原子整数
private AtomicInteger count = new AtomicInteger(0);

// 原子操作
count.incrementAndGet(); // 原子递增
count.getAndIncrement(); // 先获取再递增
count.addAndGet(10);     // 原子加法
```

### AtomicReference

```java
// AtomicReference：原子引用
private AtomicReference<String> ref = new AtomicReference<>("initial");

// 原子更新
ref.compareAndSet("initial", "new"); // CAS 操作
```

### CAS 操作

```java
// CAS：Compare And Swap
// 比较并交换
// 如果当前值等于期望值，则更新为新值

// 实现
public boolean compareAndSet(int expect, int update) {
    if (value == expect) {
        value = update;
        return true;
    }
    return false;
}
```

---

## 并发集合

### ConcurrentHashMap

```java
// ConcurrentHashMap：线程安全的 HashMap
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
map.put("key", "value");
String value = map.get("key");

// 特点：
// - 分段锁机制
// - 支持并发读写
// - 性能优于 Hashtable
```

### CopyOnWriteArrayList

```java
// CopyOnWriteArrayList：线程安全的 ArrayList
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("item");
String item = list.get(0);

// 特点：
// - 写时复制
// - 读操作无锁
// - 适合读多写少场景
```

### BlockingQueue

```java
// BlockingQueue：阻塞队列
BlockingQueue<String> queue = new LinkedBlockingQueue<>();

// 生产者
queue.put("item"); // 阻塞直到有空间

// 消费者
String item = queue.take(); // 阻塞直到有元素
```

---

## 并发编程最佳实践

### 1. 避免死锁

```java
// ❌ 问题：可能死锁
synchronized (lock1) {
    synchronized (lock2) {
        // 代码
    }
}

// 另一个线程
synchronized (lock2) {
    synchronized (lock1) {
        // 代码
    }
}

// ✅ 解决：按相同顺序获取锁
synchronized (lock1) {
    synchronized (lock2) {
        // 代码
    }
}
```

### 2. 使用并发集合

```java
// ✅ 使用并发集合
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();

// ❌ 使用同步包装
Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
```

### 3. 最小化锁范围

```java
// ✅ 最小化锁范围
public void method() {
    // 不需要同步的代码
    synchronized (this) {
        // 需要同步的代码
    }
    // 不需要同步的代码
}

// ❌ 扩大锁范围
public synchronized void method() {
    // 所有代码都在锁内
}
```

---

## 面试常见问题

### Q1: 并发和并行的区别？

**答案：**
- **并发**：同一时间段内多个任务交替执行
- **并行**：同一时刻多个任务同时执行

### Q2: 并发问题有哪些？

**答案：**
1. **竞态条件**：多线程同时修改共享数据
2. **可见性问题**：线程修改数据其他线程看不到
3. **死锁**：多个线程互相等待

### Q3: synchronized 和 Lock 的区别？

**答案：**
- **synchronized**：JVM 层面，自动释放锁
- **Lock**：API 层面，手动释放锁，更灵活

### Q4: CAS 操作？

**答案：**
- Compare And Swap：比较并交换
- 原子操作，无锁编程
- 如果当前值等于期望值，则更新

### Q5: 并发集合有哪些？

**答案：**
1. ConcurrentHashMap：线程安全的 HashMap
2. CopyOnWriteArrayList：线程安全的 ArrayList
3. BlockingQueue：阻塞队列

---

*最后更新：2024年*
