可変状態を共有しない
共有された可変状態を安全に扱う最も単純な方法は、そもそも共有しないことです。各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が各自の値を変更するだけでは解決できない問題が出てきます。例えば二つの画面から同じカウンターを増やし、更新された結果を画面にも表示したいなら、どうすればいいのでしょうか。
そこで考えることが、処理同士がどう協力しながら、同じ可変データを自由に読み書きしないで済むかです。これを解決する一つの考え方が、アクターモデルです。