Skip to content

Commit 5ed2d66

Browse files
committed
修正競態條件範例中的錯誤描述,並強調避免使用 Check-Then-Act 模式的經驗教訓
1 parent ba1603e commit 5ed2d66

File tree

1 file changed

+4
-6
lines changed

1 file changed

+4
-6
lines changed

source/_posts/2025/race-condition-in-file-storage.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ if (!await this.exists(fullPath)) {
2424
T1: 請求A 執行 this.exists(fullPath) → 返回 false (目錄不存在)
2525
T2: 請求B 執行 this.exists(fullPath) → 返回 false (目錄不存在)
2626
T3: 請求A 執行 mkdir(fullPath) → 成功建立目錄
27-
T4: 請求B 執行 mkdir(fullPath) → 可能拋出 EEXIST 錯誤
27+
T4: 請求B 執行 mkdir(fullPath) → 可能拋出 EEXIST 錯誤(fs.promises.mkdir 已在底層排除這個問題)
2828
```
2929

3030
雖然使用了 `recursive: true`,那前面的檢查很可能是不必要的行為。
@@ -103,14 +103,12 @@ await fs.promises.mkdir(fullPath, { recursive: true }) // 系統調用1: mkdir(
103103

104104
## 經驗教訓
105105

106-
1. **避免 Check-Then-Act 模式**:這是併發程式設計的經典陷阱
106+
1. **避免 Check-Then-Act 模式**:這是併發程式設計的經典陷阱,不過這次案例,執行的底層實作已處理好,所以不會有問題
107107
2. **信任系統調用**:現代 API 通常已經考慮了併發場景
108108
3. **簡單就是美**:移除不必要的檢查邏輯,程式碼更簡潔也更安全
109109

110-
## 小結
110+
## 參考
111111

112-
這次 code review 發現的問題提醒我們,併發問題往往藏在看似無害的程式碼中。「檢查然後執行」的模式在單執行緒環境下沒問題,但在併發環境下就是定時炸彈。
113-
114-
修復的核心思想很簡單:**信任系統調用,避免手動檢查**Node.js`mkdir({ recursive: true })` 就是為了處理這種情況而設計的,我們應該善用它。
112+
- [Nodejs - fsPromises.mkdir(path[, options])](https://nodejs.org/api/fs.html#fsmkdirpath-options-callback)
115113

116114
(fin)

0 commit comments

Comments
 (0)