9.4.19.1 توضیحات #
الگوی بازیابی از بنبست (Deadlock Recovery) برای شناسایی و بازیابی از وضعیتهای بنبست استفاده میشود، جایی که چندین گوروتین به طور نامحدود منتظر منابعی هستند که توسط یکدیگر نگه داشته شدهاند. بنبست میتواند به دلیل همگامسازی نادرست یا رقابت برای منابع در برنامههای همزمان رخ دهد. این الگو شامل نظارت بر گوروتینها، شناسایی بنبستهای احتمالی و پیادهسازی مکانیزمهای بازیابی مانند زمانبندی، تلاش مجدد یا خاتمه اجباری است.
9.4.19.2 دیاگرام #
flowchart TD
A[شروع] --> B[چندین گوروتین]
B --> C{منتظر منابع}
C -->|بنبست شناسایی شد| D[فعالسازی مکانیزم بازیابی]
D -->|بازیابی| E[ادامه اجرای برنامه]
C -->|بدون بنبست| F[اجرای عادی]
9.4.19.3 نمونه کد #
1package main
2
3import (
4 "fmt"
5 "sync"
6 "time"
7)
8
9func deadlockRecoveryExample() {
10 var mu1, mu2 sync.Mutex
11 done := make(chan struct{})
12
13 go func() {
14 defer func() {
15 if r := recover(); r != nil {
16 fmt.Println("بنبست شناسایی و بازیابی شد:", r)
17 }
18 }()
19 mu1.Lock()
20 defer mu1.Unlock()
21
22 time.Sleep(1 * time.Second) // شبیهسازی پردازش
23
24 mu2.Lock()
25 defer mu2.Unlock()
26 done <- struct{}{}
27 }()
28
29 go func() {
30 mu2.Lock()
31 defer mu2.Unlock()
32
33 time.Sleep(1 * time.Second) // شبیهسازی پردازش
34
35 mu1.Lock()
36 defer mu1.Unlock()
37 done <- struct{}{}
38 }()
39
40 select {
41 case <-done:
42 fmt.Println("اجرا با موفقیت به پایان رسید")
43 case <-time.After(5 * time.Second):
44 fmt.Println("بنبست رخ داد، اجرا متوقف شد")
45 }
46}
47
48func main() {
49 deadlockRecoveryExample()
50}
در کد بالا، دو گوروتین برای دسترسی به منابع mu1
و mu2
با یکدیگر رقابت میکنند که میتواند باعث بنبست شود. با استفاده از کانال و تایمر، میتوان بنبست را شناسایی و به طور مناسب مدیریت کرد.
9.4.19.4 کاربردها #
- مدیریت منابع در سیستمهای همزمان: برای جلوگیری از بنبست هنگام استفاده از منابع مشترک.
- پایگاه دادههای توزیعشده: شناسایی و بازیابی تراکنشهایی که در وضعیت بنبست قرار گرفتهاند.
- سیستمهای بلادرنگ: برای اطمینان از اینکه بنبستها باعث تأخیر غیرقابل قبول در اجرا نمیشوند.
- اشکالزدایی: استفاده از این الگو برای یافتن نقاط ضعف در طراحی همزمانی برنامه.