50072


環境:Mac/High Sierra 10.13.6/swift4.2/xcode 10.0

ある配列オブジェクトに対して、自分自身や他のいくつかのオブジェクトからの処理要求が同時に起こる可能性がある場合、命令通りに同時に処理が行われますでしょうか。  
例えば、配列でappend()をたくさん行う必要がある時に、この処理が行われている途中で他のオブジェクトなどからこの配列を参照するとどのようになりますでしょうか。

処理中のアクセス防止には排他処理を行うしか方法はありませんでしょうか。  
排他処理でも良いと思っていますが、他にも方法がある場合知りたいです。


CC BY-SA 4.0
2018-11-08T00:36:13.803
50069
2018-11-08T01:54:29.850
25745
question
swift xcode swift4
配列処理中に別のオブジェクトなどからアクセスするとどのような挙動になるのか


原則、スレッド間で共有するリソースであって複数個数のデータが入るもの（クラスなり配列なりリストなり）を、マルチスレッドで同時操作する場合には必ず排他制御が必要です。１つのデータであってもアトミックアクセスできないものは排他なり、処理系が提供していればアトミック操作命令が必要です。

例：座標データ `(x, y)` があるとき、排他しないと  
\- スレッド１が `x` を読む  
\- スレッド２が `x` を書く  
\- スレッド２が `y` を書く  
\- スレッド１が `y` を読む  
と、スレッド１が処理しようとする座標は旧値でも新値でもない壊れた値となります。

例： 32bit CPU で 64bit 変数１つを扱うとき、排他しないと  
\- スレッド１が下位 32bit を読む  
\- スレッド２が下位 32bit を読む  
\- スレッド２が上位 32bit を読む  
\- スレッド２は 64bit 値に対して演算を行う  
\- スレッド２が下位 32bit を書く  
\- スレッド２が上位 32bit を書く  
\- スレッド１が上位 32bit を読む  
と、やはりスレッド１が読み取った値は壊れた値です。

というわけで１つの変数に対する処理であっても排他が必要となる場合があります。

処理系によっては「アトミック操作」命令を提供してくれているものもあります。そういう場合アトミック操作命令をうまく使うと排他不要になる場合もあります。例：
Windows API であれば `InterlockedIncrement` 等。

> 命令通りに同時に処理が行われますでしょうか。

No! 最近の高速 CPU
ではキャッシュメモリやパイプラインの活用のためコア１とコア２で「書き込んだ順番と読み込んだ順番が逆に見えてしまう」ことすらあります。「メモリバリア」なる機能でそういう不具合を回避することができますが実行コストが高いです（とはいえ排他よりは安い）。マルチスレッド構成で最高の実行時性能を追求するにはどういう状況でどういう処理が必要かの深い理解が必要となります。開発コストを下げたいのであれば排他するほうが簡単。  
<https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%A2%E3%83%AA%E3%83%90%E3%83%AA%E3%82%A2>


CC BY-SA 4.0
2018-11-08T01:54:29.850
50072
2018-11-08T01:54:29.850
8589
50069
answer