WWDC21-Concurrency-Actors

1.前言

  • 数据竞争使得并发更加困难。代码很琐碎、很难调试
  • async task不能捕获mutable变量

2.Actors

  • actors为共享的mutable变量提供synchornization
  • actors的属性是和其他代码分离开的
    • 要想访问actors的属性,只能通过actors
    • actors的访问机制会保证没有数据竞争
1
2
3
4
5
6
7
8
9
10
11
12
struct Counter {
var value = 0
mutating func increment() -> Int { // 若在两个任务中调用,会产生数据竞争
value = value + 1
return value
}
}

actor Counter {
var value = 0
func increment() -> Int { ... } // 不会产生数据竞争
}

3. Actor reentrancy

  • actor中在运行一段可能会导致任务suspend的代码(await)时,可能会导致actor的状态变化,此时需要在resumption时检查

    • actor ImageDownloader {
          private var cache: [URL: Image] = [:]
          func image(from url: URL) async throws -> Image? {
              if let cached = cache[url] {
                  return cached
              }
              let image = try await downloadImage(from: url)
              // Potential bug: `cache` may have changed.
              cache[url] = image
              return image
          }
      }
      <!--1-->
      
      * 
      

4.Actor Isolation

  • actor isolation 是actor类型的基本原则

  • actor也可以遵循协议

    • actor LibraryAccount {
          let idNumber: Int
          var booksOnLoan: [Book] = []
      }
      <!--2-->
    • nonisolation 可以在actor外面运行

      • extension LibraryAccount: Hashable {
            nonisolated func hash(into hasher: inout Hasher) {
                hasher.combine(idNumber) // 只能访问imutable变量,不能访问mutable变量(例:bookOnloan)
            }
        }
        <!--3-->
    • detached task中的闭包不是isolated

      • extension LibraryAccount {
            func readSome(_ book: Book) -> Int { ... }
            func read() -> Int { ... }
        
            func readLater() {
                asyncDetached {
                    await read() // 不是isolated,因此要访问read必须加上await
                }
            }
        }

5.Sendable

  • 用来解决数据冲突
  • actor中使用值类型是安全的
  • actor中使用引用类型(class)是不安全的
    • 此时可以使用@Sendable
  • Sendable可以在不同的actor中共享
  • 很多类型可以是sendable
    • 值类型
    • Actor类型
    • immutable class(类他本身及子类只能包含imutable属性)
    • internally-synchornized class (类内只有同步操作)
    • @Sendable函数
  • Sendable类型不会有数据竞争问题
  • swift会禁止非Sendable类型共享
  • 让自定义类型遵循Sendable协议,swift会自动检查
  • @Sendable函数
    • 也遵循Sendable协议
    • 对闭包有一些限制
      1. 不能捕获mutable变量
      2. 捕获的也要是Sendable类型
      3. 同步的闭包,不能是actor-isolated。因为可能会使代码在actor外运行

6.Main Actor

  • 代表主线程的actor
    • 所有的异步操作都是在主线程完成
    • 主线程的代码和数据分散的到处都是
  • swift会自动保证代码运行在主线程,不再需要手动确保
  • 类型也可以设为mainActor
0%