Swift Actor中发生数据争用

xmjla07d  于 2023-01-16  发布在  Swift
关注(0)|答案(2)|浏览(102)

我使用Thread Sanitizer在Swift应用程序中发现了一个数据竞争,因此我第一次尝试修复竞争条件,将违规的class转换为actor。竞争导致的崩溃似乎已经消失,但Thread Sanitizer仍然说代码中存在数据竞争,我认为这在actor中应该是不可能的。
我不能在这里发布整个actor,但这里是发生竞争的代码:

actor SampleActor {
    private var things = Set<Int>()
    
    func addThing(_ newThing: Int, seconds: Double) {
        things.insert(newThing)
        Task {
            try await Task.sleep(nanoseconds: UInt64(seconds * 1_000_000_000))
            self.things.remove(newThing)
        }
    }
}

// Code to cause the race
let sample = SampleActor()
for n in 0 ..< 1000 {
    Task {
        await sample.addThing(n, seconds: Double.random(in: 0...1.0))
    }
}

我可能用了错误的方法,但是我需要向SampleActor的对象集中添加一个对象,并在一段时间后自动删除它。
有没有更好的方法来做到这一点?在使用actor来避免这种情况下的数据竞争方面,我遗漏了什么?SampleActor.things不应该对这里的竞争免疫吗,因为它是actor的属性?

goqiplq2

goqiplq21#

卸下actor中的Task {部件
async添加到函数

func addThing(_ newThing: Int, seconds: Double) async {
tgabmvqs

tgabmvqs2#

这里没有数据竞争。这是TSAN中的一个bug。据报道,他们一直在改进它与参与者的交互,但至少在Swift 5.7.2中,仍然存在问题。例如,请参见https://github.com/apple/swift/issues/57902https://github.com/apple/swift/issues/57749
正如lorem ipsum所说(+1),在addThing中放弃使用Task {…}是明智的,这样可以获得更简洁的代码,享受结构化并发的好处,但这不是这里的问题,暂时避免使用具有Swift并发的TSAN。

相关问题