🦀
Swiftのactor(class)の動きを確認
actorの簡単な説明
classと同じように書けて、並列処理をした場合のデータの競合性を保証してくれるもの
確認するコード
Counterを用意して、1秒かけてcountに1足す関数update()関数を並列でよびだすというコードで動きを確認します。
class Counter {
var count: Int = 0
func update() async -> Int {
try! await Task.sleep(for: .seconds(1))
count += 1
return count
}
}
実行コード
並列コードにはasync let
を使用している
以下のコードは1秒かかるupdate()を5つ実行しているが、並列(async let)で実行しているため、5秒ではなく、1秒で終了する
let counter = Counter()
async let value1 = counter.update()
async let value2 = counter.update()
async let value3 = counter.update()
async let value4 = counter.update()
async let value5 = counter.update()
let values = await [value1, value2, value3, value4, value5]
print(values)
実行結果(class)
何度か実行してみた結果
- 結果内容の順番は並列で行われているため保証されていない
- classではデータの競合が保証されていないため同じデータがある
[4, 2, 1, 5, 3]
[3, 1, 4, 2, 5]
[4, 3, 2, 2, 5] // `2`が2回出てしまっている
actorで実行
最初のコードCounterをclassからactorに置き換えます。
これを同じ実行コードで実行すると、2
が2回出るなどのデータ競合は起こらなくなります。
これがactorの動きです。
コード全体
actor/*class*/ Counter {
var count: Int = 0
func update() async -> Int {
try! await Task.sleep(for: .seconds(1))
count += 1
return count
}
}
let counter = Counter()
async let value1 = counter.update()
async let value2 = counter.update()
async let value3 = counter.update()
async let value4 = counter.update()
async let value5 = counter.update()
let values = await [value1, value2, value3, value4, value5]
print(values)
Discussion