死锁

死锁条件

避免死锁的方法

那么避免死锁问题就只需要破环其中一个条件就可以,最常见的并且可行的就是使用资源有序分配法,来破环环路等待条件。

代码示例:

package main

import (
	"fmt"
	"sync"
	"time"
)

var A = sync.Mutex{}
var B = sync.Mutex{}

// goroutineA 协程函数 A
func goroutineA() {
	fmt.Printf("thread A waiting get ResourceA \n")
	A.Lock()
	fmt.Printf("thread A got ResourceA \n")

	time.Sleep(1 * time.Second)

	fmt.Printf("thread A waiting get ResourceB \n")
	B.Lock()
	fmt.Printf("thread A got ResourceB \n")

	A.Unlock()
	B.Unlock()
	return
}

// goroutineB 协程函数 B
func goroutineB() {
	fmt.Printf("thread B waiting get ResourceB \n")
	B.Lock()
	fmt.Printf("thread B got ResourceB \n")

	time.Sleep(1 * time.Second)

	fmt.Printf("thread B waiting get ResourceA \n")
	A.Lock()
	fmt.Printf("thread B got ResourceA \n")

	A.Unlock()
	B.Unlock()
	return
}

// goroutineBSolved 协程函数 B
func goroutineBSolved() {
	fmt.Printf("thread B waiting get ResourceA \n")
	A.Lock()
	fmt.Printf("thread B got ResourceA \n")

	time.Sleep(1 * time.Second)

	fmt.Printf("thread B waiting get ResourceB \n")
	B.Lock()
	fmt.Printf("thread B got ResourceB \n")

	A.Unlock()
	B.Unlock()
	return
}

资源循环引用

	//创建两个协程
	go func() {
		goroutineA()
		fmt.Println("A finish")
	}()
	go func() {
		goroutineB()
		fmt.Println("B finish")
	}()
	<-time.After(3 * 60 * time.Second)
	return

死锁:

thread A waiting get ResourceA 
thread A got ResourceA 
thread B waiting get ResourceB 
thread B got ResourceB 
thread B waiting get ResourceA 
thread A waiting get ResourceB 

资源顺序引用,破解循环

	//创建两个协程
	go func() {
		goroutineA()
		fmt.Println("A finish")
	}()
	go func(){
		goroutineBSolved()
		fmt.Println("B finish")
	}()

不会死锁:

thread A waiting get ResourceA 
thread A got ResourceA 
thread B waiting get ResourceA 
thread A waiting get ResourceB 
thread A got ResourceB 
A finish
thread B got ResourceA 
thread B waiting get ResourceB 
thread B got ResourceB 
B finish
支付宝打赏 微信打赏

来杯咖啡~

文章导航