【问题标题】:How to fix Simultaneous accesses to '', but modification requires exclusive access in Swift Graph如何修复同时访问“”,但修改需要在 Swift Graph 中进行独占访问
【发布时间】:2019-04-14 15:33:39
【问题描述】:

我正在尝试在 Swift 中创建图形,但是当我尝试对其运行 containsCycle() 方法时出现以下错误:同时访问 0x6000034cd220,但修改需要独占访问。原谅我,但我不明白其他类似(但不一样)的问题,所以我问了一个更具体的问题。感谢您的帮助!

class Node: Hashable {
    var val: String
    var neighbors = Set<Node>()

    init(val: String) {
        self.val = val
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(val)
        hasher.combine(neighbors)
    }

    static func == (lhs: Node, rhs: Node) -> Bool {
        return lhs.hashValue == rhs.hashValue
    }
}

let a = Node(val: "a")
let b = Node(val: "b")
let c = Node(val: "c")
let d = Node(val: "d")
let e = Node(val: "e")
let f = Node(val: "f")
let g = Node(val: "g")
let h = Node(val: "h")
let i = Node(val: "i")
let j = Node(val: "j")
let k = Node(val: "k")

a.neighbors.insert(b)
a.neighbors.insert(c)
a.neighbors.insert(d)
a.neighbors.insert(e)

d.neighbors.insert(d) // <-- crashes here
d.neighbors.insert(a) // <-- or here, if I comment out the line above

c.neighbors.insert(g)
c.neighbors.insert(h)
c.neighbors.insert(a)

g.neighbors.insert(h)
g.neighbors.insert(c)

h.neighbors.insert(g)
h.neighbors.insert(c)

b.neighbors.insert(a)

e.neighbors.insert(a)
e.neighbors.insert(i)
e.neighbors.insert(j)
e.neighbors.insert(k)

i.neighbors.insert(e)

j.neighbors.insert(e)

k.neighbors.insert(k)

containsCycle() 用于上下文,但我的问题与以上所有内容有关。

func containsCycle(_ node: Node) -> Bool {
    var seen = Set<Node>()
    return containsCycleRec(node, parent: nil, seen: &seen)
}

func containsCycleRec(_ node: Node, parent: Node?, seen: inout Set<Node>) -> Bool {
    seen.insert(node)
    for neighbor in node.neighbors {
        if !seen.contains(neighbor) {
            containsCycleRec(neighbor, parent: node, seen: &seen)
        } else if neighbor != parent {
            return true
        }
    }
    return false
}

【问题讨论】:

  • 您说“当我尝试针对它运行 containsCycle() 方法时出现以下错误”。但您也说d.neighbors.insert(d) // &lt;-- crashes here。您要问的是哪个问题?请显示只有一个问题的工作代码,以便我们理解,并清楚地标记那个问题的位置和内容。谢谢。
  • 另外:您说您不了解同一问题的其他答案。但是您正在做完全会导致问题的事情:您将结构(Set)作为inout 传递并修改它(seen.insert)。所以在我看来,在这个程度上,这是重复的。 (我可能错了,但没有实际运行和测试你的代码,这是一个显而易见的缺陷。)
  • 我认为您已经在第二个声明中回答了这个问题。如果我理解正确,因为 set 是一个结构,而不是引用类型,它不能通过 inout 修改(因为它是一个副本),这就是错误的来源。通过使用另一个数据结构放弃 O(1) 查找和插入似乎是一种耻辱。如果 Set 是一个类,如果我理解正确的话,我正在做的事情会起作用。
  • 它可以被inout修改,这就是问题所在(我建议)。

标签: swift


【解决方案1】:

给定 2 个相互包含作为邻居的节点,它会创建一种无限循环,(在我的理解中)编译器不知道它们之间的引用循环在哪里结束。所以,他们都试图同时修改对方。

a.neighbors.contains(d) // returns true
d.neighbors.contains(a) // returns true

由于这是一个图问题,一个很好的解决方案最终是将图表示为邻接列表,而不是一系列相互引用的节点。

let adjList = [
    "a": ["d"],
    "d": ["a"]
]

我可能是错的(我很高兴学到新东西),但这是我对问题的理解和解决方案。

【讨论】:

    猜你喜欢
    • 2019-01-11
    • 2018-03-07
    • 1970-01-01
    • 2019-05-06
    • 1970-01-01
    • 2018-02-21
    • 2019-10-28
    • 2018-02-17
    • 2018-01-07
    相关资源
    最近更新 更多