feat: rename Golang files to Chinese and supplement root files

Changes:
- Renamed all 10 Golang files from English to Chinese names
- Created 00-项目概述/项目概述.md with comprehensive project overview
- Created 08-算法与数据结构/算法与数据结构学习指南.md with detailed learning guide
- Created 12-面试技巧/面试准备进度.md with progress tracking
- Added .obsidian configuration for better markdown editing
- Updated Claude.MD with Chinese filename rule

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

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
yasinshaw
2026-03-01 00:33:32 +08:00
parent ab3a99f131
commit 7f3ab362b3
21 changed files with 1903 additions and 0 deletions

View File

@@ -0,0 +1,240 @@
# Golang 并发编程进阶
## 问题
1. sync.Mutex 和 sync.RWMutex 的区别?
2. sync.WaitGroup 和 sync.Once 的使用场景?
3. atomic 包的作用是什么?
4. 如何实现一个无锁队列?
5. 如何检测数据竞争Data Race
6. Go 的内存模型Happens-Before是什么
---
## 标准答案
### 1. Mutex vs RWMutex
#### **Mutex互斥锁**
```go
var mu sync.Mutex
func write() {
mu.Lock()
defer mu.Unlock()
// 写操作
}
```
---
#### **RWMutex读写锁**
```go
var mu sync.RWMutex
func read() {
mu.RLock()
defer mu.RUnlock()
// 读操作(多个 Goroutine 可以同时读)
}
func write() {
mu.Lock()
defer mu.Unlock()
// 写操作(独占访问)
}
```
---
**使用场景**
- **Mutex**:读写都少
- **RWMutex**:读多写少
---
### 2. WaitGroup 和 Once
#### **WaitGroup**
**用途**:等待一组 Goroutine 完成
```go
var wg sync.WaitGroup
func worker(id int) {
defer wg.Done()
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
}
func main() {
for i := 1; i <= 3; i++ {
wg.Add(1)
go worker(i)
}
wg.Wait() // 等待所有 worker 完成
fmt.Println("All workers done")
}
```
---
#### **Once**
**用途**:确保函数只执行一次
```go
var once sync.Once
func initDB() {
once.Do(func() {
// 初始化数据库(只执行一次)
fmt.Println("DB initialized")
})
}
func main() {
initDB()
initDB() // 不会再次执行
}
```
---
### 3. atomic 包
#### **作用**
**原子操作**:无锁并发编程
---
#### **示例**
```go
import "sync/atomic"
var counter int64
// ❌ 非原子操作(数据竞争)
func increment() {
counter++ // 不是原子操作
}
// ✅ 原子操作
func incrementAtomic() {
atomic.AddInt64(&counter, 1)
}
// 读取
value := atomic.LoadInt64(&counter)
// 比较并交换CAS
old := atomic.LoadInt64(&counter)
atomic.CompareAndSwapInt64(&counter, old, new)
```
---
### 4. 检测数据竞争
#### **使用 go test -race**
```bash
# 检测数据竞争
go test -race ./...
# 运行程序
go run -race main.go
```
---
#### **示例**
```go
// ❌ 有数据竞争
func main() {
var counter int
go func() {
counter++ // 数据竞争
}()
counter++ // 数据竞争
}
// ✅ 无数据竞争
func main() {
var counter int64
go func() {
atomic.AddInt64(&counter, 1)
}()
atomic.AddInt64(&counter, 1)
}
```
---
### 5. Happens-Before
#### **定义**
**Happens-Before**:保证一个操作对另一个操作可见
---
#### **规则**
1. **Goroutine 创建**`go func()` happens-before `func()` 开始
2. **Channel**:发送 happens-before 接收
3. **Lock**Unlock happens-before 下一次 Lock
---
#### **示例**
```go
var a, b int
func main() {
go func() {
a = 1 // ①
ch <- struct{}{} // ②
}()
b = 2 // ③
<-ch // ④
// 保证了:
// ① happens-before ②
// ② happens-before ④
// 因此a = 1 一定会在 b = 2 之前执行
}
```
---
### 6. 阿里 P7 加分项
**深度理解**
- 理解 Go 的内存模型Happens-Before
- 理解 atomic 包的实现原理CAS
- 理解 RWMutex 的实现(写锁饥饿问题)
**实战经验**
- 有使用 -race 检测数据竞争的经验
- 有优化并发程序的经验(减少锁、使用 atomic
- 有实现无锁数据结构的经验
**并发编程**
- 理解如何避免数据竞争
- 理解如何使用原子操作
- 理解如何实现高性能并发程序