Go language learning ----- concurrent way deadlock, livelock and starvation

Deadlock, livelock and starvation

1, deadlock

死锁:会使得所有并发程序在等待,如果没有外界干预,程序不能恢复
type values struct{
	mu sync.Mutex
	value int
}
func TestMutes(v1, v2 *values){
	defer wg.Done()
	v1.mu.Lock()
	defer v1.mu.Unlock()
	time.Sleep(2*time.Second)
	v2.mu.Lock()
	defer v2.mu.Unlock()
	fmt.Println("v1+v2=:",v1.value+v2.value)
}

var wg sync.WaitGroup
func main(){
	var a = values{
		value:1,
		mu:sync.Mutex{},
	}
	var b = values{
		value: 2,
		mu:sync.Mutex{},
	}
	wg.Add(2)
	go TestMutes(&a,&b)
	go TestMutes(&b,&a)
	wg.Wait()
}
fatal error: all goroutines are asleep - deadlock!

Produced by matter of time before the deadlock, the time code is run:
A deadlock caused by a matter of time
detect, prevent and correct the deadlock four ways:

  • Mutually exclusive: concurrent processes also have exclusive rights to resources
  • Wait Condition: concurrent processes must have both a resource and waiting for additional resources
  • No preemption: concurrent processes can only be released with the resources of the process
  • Loop waiting for: a concurrent process p1 must wait for a range of other concurrent processes p2, p2 p1 also waiting for
    the code above goroutine resources can not do (no preemption)

2, Livelock

Livelock: the implementation of the program is actively concurrent operations, but these operations can not advance the state of the program forward

//模拟人通过走廊
func main(){
	cadence := sync.NewCond(&sync.Mutex{})
	go func(){
		for range time.Tick(1 *time.Millisecond){
			cadence.Broadcast()
		}
	}()
	takeStep := func(){
		cadence.L.Lock()
		cadence.Wait()
		cadence.L.Unlock()
	}
	//tryDir允许一个人尝试一个方向移动
	tryDir := func(dirName string, dir *int32, out *bytes.Buffer)bool{
		fmt.Fprintf(out,"%v",dirName)
		atomic.AddInt32(dir,1)//向一个方向移动
		takeStep()	//每个人每次移动的节奏一样
		if atomic.LoadInt32(dir)==1{
			fmt.Fprintf(out,".Success!")
			return true
		}
		takeStep()
		atomic.AddInt32(dir,-1)//表示不能走放弃
		return false
	}
	var left, right int32
	tryLeft := func(out *bytes.Buffer)bool{return tryDir(" left ",&left,out)}
	tryRight := func(out *bytes.Buffer) bool{return tryDir(" right ",&right,out)}
	walk := func(walking *sync.WaitGroup, name string){
		var out bytes.Buffer
		defer func() {fmt.Println(out.String())}()
		defer walking.Done()
		fmt.Fprintf(&out, "%v is trying to scoot:",name)
		for i := 0; i < 5; i++{//对尝试次数进行限制
			if tryLeft(&out) || tryRight(&out){//首先会尝试向左
				return
			}
		}
		fmt.Fprintf(&out,"\n%v hello!",name)
	}
	var peopleIn sync.WaitGroup//模拟两个人
	peopleIn.Add(2)
	go walk(&peopleIn,"tom")
	go walk(&peopleIn,"alice")
	peopleIn.Wait()
}
//结果:
//alice is trying to scoot: left  right  left  right  left  right  left  right  left  right 
alice hello!
tom is trying to scoot: left  right  left  right  left  right  left  right  left  right 
tom hello!
tom和alice在退出之前会持续竞争

3, hunger

Hunger: that in any case, concurrent processes are unable to obtain all the resources needed for the implementation of
hunger usually refers to one or more concurrent processes share of resources, so that other processes can not possess the resources to perform

var wg sync.WaitGroup
	var sharedLock sync.Mutex
	const runtime = 1 * time.Second
	greedyWorker := func(){
		defer wg.Done()
		var count int
		for begin := time.Now(); time.Since(begin) <= runtime; {
			sharedLock.Lock()
			time.Sleep(3*time.Nanosecond)
			sharedLock.Unlock()
			count++
		}
		fmt.Printf("Greedy worker was able to execute %d work loops\n",count)
	}
	politeWorker := func(){
		defer wg.Done()
		var count int
		for begin := time.Now(); time.Since(begin) <= runtime; {
			sharedLock.Lock()
			time.Sleep(1*time.Nanosecond)
			sharedLock.Unlock()
			sharedLock.Lock()
			time.Sleep(1*time.Nanosecond)
			sharedLock.Unlock()
			sharedLock.Lock()
			time.Sleep(1*time.Nanosecond)
			sharedLock.Unlock()
			count++
		}
		fmt.Printf("Polite worker was able to execute %d work loops\n",count)
	}
	wg.Add(2)
	go greedyWorker()
	go politeWorker()
	wg.Wait()
结果: Greedy worker was able to execute 297 work loops
			Polite worker was able to execute 99 work loops
			从结果中可以看出greedyWorker扩大了其持有共享锁的临界区,并阻止了politeWorker的高效工作

Hunger can lead to poor performance or program error, it is possible to make procedural error, if the example above, greedy polite completely prevented the completion of the work, it will make polite never be executed
during memory access sync, sync and need to coarse-grained Fine-grained synchronization to find a balance between, in order to improve the performance of programs

Guess you like

Origin blog.csdn.net/alvin_666/article/details/90575032