活锁----golang

91 阅读1分钟

代码模拟两人在相遇时,同时向左或向右为对方让路导致互相无法通过

package main

import (
	"bytes"
	"fmt"
	"sync"
	"sync/atomic"
	"time"
)

func main() {

	cadence := sync.NewCond(&sync.Mutex{})
	go func() { //1
		for range time.Tick(1 * time.Millisecond) {

			cadence.Broadcast()
		}
	}()

	takeStep := func() { //2
		cadence.L.Lock()
		cadence.Wait()
		cadence.L.Unlock()
	}

	tryDir := func(dirName string, dir *int32, out *bytes.Buffer) bool { 
		fmt.Fprintf(out, " %v", dirName)
		atomic.AddInt32(dir, 1) 
		takeStep() //2              
		if atomic.LoadInt32(dir) == 1 {
			fmt.Fprint(out, ". Success!")
			return true
		}
		takeStep() //2
		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 walking.Done()
		defer func() { fmt.Println(out.String()) }()
		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 tosses her hands up in exasperation!", name)
	}

	var peopleInHallway sync.WaitGroup
	peopleInHallway.Add(2)
	go walk(&peopleInHallway, "Alice")
	go walk(&peopleInHallway, "Barbara")
	peopleInHallway.Wait() //3
}

  1. 定时进行唤醒工作,同时唤醒然后进行移动
  2. 让双方都停止在移动的前一刻,等待被唤醒
  3. 防止主程序退出