Skip to content

可変状態を共有しない

共有された可変状態を安全に扱う最も単純な方法は、そもそも共有しないことです。各Taskが別々の値を持てば、片方のTaskによる変更は、もう片方のTaskに影響しません。

例として、先ほどのCounterを参照型のclassではなく、値型のstructを使って再実装します。increment()は自分のvalueを書き換えるので、mutatingを付けます。

struct Counter {
var value = 0
mutating func increment() -> Int {
value = value + 1
return value
}
}
func runWithCopies() {
let counter = Counter()
Task.detached {
var localCounter = counter
print(localCounter.increment()) // 1
}
Task.detached {
var localCounter = counter
print(localCounter.increment()) // 1
}
}

structは値型です。各Taskのvar localCounter = counterでは、それぞれがcounterのコピーがlocalCounterに代入されます。AのTaskが値を増やしても、BのTaskが持つ値は変わりません。両方が0から始めるので、二つの出力は1と1です。

元のclass Counterでは、二つのTaskが同じインスタンスを指していました。今回のstruct Counterでは、二つのTaskがそれぞれ自分の値を変更します。

ただし、実際のアプリケーションでは、Taskが各自の値を変更するだけでは解決できない問題が出てきます。例えば二つの画面から同じカウンターを増やし、更新された結果を画面にも表示したいなら、どうすればいいのでしょうか。

そこで考えることが、処理同士がどう協力しながら、同じ可変データを自由に読み書きしないで済むかです。これを解決する一つの考え方が、アクターモデルです。