한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

遊戲 Lag 白皮書 › L9 伺服器遊戲程式

死結 Deadlock

原因 ID sp-deadlock · 主要負責 遊戲開發團隊(伺服器開發)

在含圖解與實驗的完整版中開啟卡片 →

兩個執行緒各自等待對方持有的鎖時,就會永遠停住。

為什麼 執行緒 A 持有鎖 1 並等待鎖 2,B 持有鎖 2 並等待鎖 1 → 於是 兩者都永遠停住,相關的執行緒也接連停住 → 畫面上 整台伺服器停止運作,看門狗(watchdog)重新啟動時所有人斷線

症狀
定格, 斷線
因素
停滯
誰會遇到
整個伺服器, 只有特定功能
何時
偶爾隨機發生, 人潮湧入時
負責單位
主要負責 遊戲開發團隊(伺服器開發)
遊戲開發團隊要做的事
制定取鎖順序規則、使用有逾時的鎖、加入看門狗並在停住的瞬間留下 thread dump。
圖表上
連線同時大量中斷 · 連線數、伺服器傳送量
查看位置
停住期間擷取所有執行緒的呼叫堆疊。JVM 用 jstack(會自動找出並標示死結),.NET 用 dotnet-stack,原生伺服器用 gdb 的 thread apply all bt,或先用 gcore 擷取 core 檔案,重新啟動後再分析
符合的跡象
兩個以上的執行緒停在等待對方所持有鎖的堆疊上,這段期間處理程序的 CPU 使用率接近 0
不符合的跡象
停住期間有一個執行緒以 CPU 100% 在跑時是無窮迴圈。執行緒都在等 DB 或外部回應時,是同步呼叫或執行緒池耗盡
確認方式
用基礎設施工具確認(不需要遊戲程式碼)

出處

  1. Runtime locking correctness validator Linux kernel
    以相反順序取得兩個鎖時,會因循環等待而死結(lock inversion deadlock);Linux kernel 會檢查取鎖順序並事先警告
  2. Liveness, Readiness, and Startup Probes Kubernetes
    以 liveness probe 偵測「仍在執行卻無法前進」的死結狀態,並重新啟動容器
  3. Diagnostic Tools (Java SE 21 Troubleshooting Guide) Oracle
    jstack 會輸出執行中 JVM 所有執行緒的堆疊,也會找出並標示死結(Found one Java-level deadlock)
  4. dotnet-stack diagnostic tool - .NET CLI Microsoft
    擷取並輸出 .NET 處理程序所有執行緒的 managed 堆疊
  5. Threads (Debugging with GDB) GNU Project
    以 thread apply all 對所有執行緒執行同一個指令(bt:輸出呼叫堆疊)
  6. gcore(1) — Linux manual page gdb
    為執行中的程式產生 core 檔案,產生後程式仍繼續執行

相關原因

同一層:L9 伺服器遊戲程式

同一症狀(定格)在其他層的原因

查看含圖解與實驗的完整版卡片