【问题标题】:Why am I getting deadlock and how to fix it (synch)?为什么会出现死锁以及如何修复它(同步)?
【发布时间】:2021-11-08 02:01:49
【问题描述】:

在某处陷入僵局。是什么原因造成的,应该如何解决? 试图创造一个分子创造。函数 Make 将输入作为字符串:

func testMolecule() {
    water := New()
    water.Make("HOH")   // water.Make("OOHHHH")
    fmt.Println(water.Molecules())
    // Output: 1
}

函数应返回创建的分子数。分子应该有 1 个 O 分子和 2 个 H 分子。 在创建所有分子之前不应执行生产功能。

import (
    "sync"
)

// Water structure holds the synchronization primitives and
// data required to solve the water molecule problem.
// moleculeCount holds the number of molecules formed so far.
// result string contains the sequence of "H" and "O".
// wg WaitGroup is used to wait for goroutine completion.
type Water struct {
    sync.Mutex
    wg            sync.WaitGroup
    cond          *sync.Cond
    moleculeCount int
    result        string
    assignedO     int
    assignedH     int
    finished      bool


}

// New initializes the water structure.
func New() *Water {
    water := &Water{
        moleculeCount: 0,
        result:        "",
        assignedO:     0,
        assignedH:     0,
        finished:      false,
    }
    water.cond = sync.NewCond(water)
    return water
}

// releaseOxygen produces one oxygen atom if no oxygen atom is already present.
// If an oxygen atom is already present, it will block until enough hydrogen
// atoms have been produced to consume the atoms necessary to produce water.
//
// The w.wg.Done() must be called to indicate the completion of the goroutine.
func (w *Water) releaseOxygen() {
    defer w.wg.Done()
    for {
        w.Lock()
        if w.assignedO == 0 {
            w.assignedO = 1

        }
        for !(w.assignedH == 2) {

            w.cond.Wait()
        }
        w.result = w.result + "O"
        w.cond.Broadcast()
        w.Unlock()
    }

}

// releaseHydrogen produces one hydrogen atom unless two hydrogen atoms are already present.
// If two hydrogen atoms are already present, it will block until another oxygen
// atom has been produced to consume the atoms necessary to produce water.
//
// The w.wg.Done() must be called to indicate the completion of the goroutine.
func (w *Water) releaseHydrogen() {
    defer w.wg.Done()
    for {
        w.Lock()
        if w.assignedH < 2 {
            w.assignedH = w.assignedH + 1

        }
        for !(w.assignedO == 1) && w.assignedH == 2 {
            w.cond.Wait()
        }
        w.result = w.result + "HH"
        w.cond.Broadcast()
        w.Unlock()
    }
}

// produceMolecule forms the water molecules.
func (w *Water) produceMolecule(done chan bool) {
    for {
        w.Lock()
        for w.assignedO == 1 && w.assignedH == 2 && !w.finished {
            w.cond.Wait()
        }
        if w.assignedO == 0 && w.assignedH == 0 && w.finished {
            w.Unlock()
            break
        }
        w.moleculeCount = w.moleculeCount + 1
        w.assignedH = 0
        w.assignedO = 0
        w.cond.Broadcast()
        w.Unlock()
    }

    done <- true
}

func (w *Water) finish() {
    w.Lock()
    w.finished = true
    w.cond.Broadcast()
    w.Unlock()

}

func (w *Water) Molecules() int {
    return w.moleculeCount
}

// Make returns a sequence of water molecules derived from the input of hydrogen and oxygen atoms.
func (w *Water) Make(input string) string {
    done := make(chan bool)
    go w.produceMolecule(done)
    for _, ch := range input {
        w.wg.Add(1)
        switch ch {
        case 'O':
            go w.releaseOxygen()
        case 'H':
            go w.releaseHydrogen()
        }
    }
    w.wg.Wait()
    w.finish()
    <-done
    return w.result
}

【问题讨论】:

    标签: go synchronization deadlock data-race


    【解决方案1】:

    函数应返回创建的分子数。分子应该有1个O分子和2个H分子。

    您不需要任何同步或并发。只需计算 Os、Hs,然后返回 O 的数量或 H 的一半数量中的较小者。

    https://play.golang.org/p/3FaJDMi5ER7

    从上一个问题中我知道您可能正在尝试构建某种模拟或模型,但我不明白您的目标。

    【讨论】:

    • 我正在尝试使用同步、协作同步并尝试使用条件变量来实现,即sync.Cond。
    猜你喜欢
    • 2011-10-21
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多