Swift中的Actor和MainActor:防止数据竞争的并发编程

Viewed 0

Swift Actor 与 MainActor:并发编程中的数据竞争防护

Actor 是 Swift 并发编程模型中的一个关键概念,归属于多线程编程模块,其主要目的是防止数据竞争,即多个线程同时访问共享资源导致的不可预测行为。

数据竞争问题

在传统类中,如果多个线程同时修改同一属性,就会发生数据竞争。以下示例展示了这一问题:

class ActorTest {
    var count = 0
    func add() {
        count += 1
        print(count, Thread.current, Date().timeIntervalSince1970)
    }
}

let test = ActorTest()
for _ in 0...5 {
   Task.detached {
     test.add()
   }
}
// 打印结果:多个线程同时访问,出现数据竞争,导致数据不准确

输出显示计数值混乱,证明了数据竞争的存在。

使用 Actor 解决数据竞争

Swift 引入了 Actor 类型来隔离状态,确保同一时间只有一个任务可以访问其可变状态。将类改为 actor 即可避免竞争:

actor ActorTest {
    var count = 0
    func add() {
        count += 1
        print(count, Thread.current, Date().timeIntervalSince1970)
    }
}

let test = ActorTest()
for _ in 0...5 {
   Task.detached {
     await test.add()
   }
}
// 打印结果:顺序执行,无数据竞争

此时,计数按顺序递增,所有操作在同一个线程上执行,确保了数据一致性。

MainActor:主线程执行

对于需要在主线程更新 UI 的场景,可以使用 @MainActor 属性。将类标记为 @MainActor 可确保其方法在主线程执行:

@MainActor class ActorTest {
    var count = 0
    func add() {
        count += 1
        print(count, Thread.current, Date().timeIntervalSince1970)
    }
}
let test = ActorTest()
for _ in 0...5 {
   Task.detached {
     await test.add()
   }
}
// 打印结果:所有操作在主线程中执行

输出确认了执行线程为主线程,适用于 UI 更新。

通过 Actor 和 MainActor,Swift 为并发编程提供了安全、高效的解决方案,有效防止数据竞争并简化多线程代码的编写。

0 Answers