「しかし、第5章『マルチスレッド』の補遺の割に、ちっともマルチスレッドじゃない」
とお嘆きの読者様。朗報です。やっとマルチスレッドの話です。
__block変数への書き込みってスレッドセーフ??
GCDのdispatch_applyで、Global QueueにBlock突っ込むと、それはもう簡単に複数スレッドから同時に__block変数を書き換えることができます。
... あ、もしかして、GCDことGrand Central Dispatch、よくご存知でなかったりしますでしょうか? そういう話でしたら、それはもう詳しく説明している本がありますので、この場を借りてご紹介できればな、と思います。
『iOS 4プログラミングブック』- ■5-3 Grand Central Dispatchの概要
- ■5-4 Grand Central Dispatchの解説
- ■5-4 Grand Central Dispatchの解説
はい、宣伝させていただいてありがとうございます。dispatch_applyでガンガン__blockを書き換えるソースを書いてみます。
#import <dispatch/dispatch.h>
#import <stdio.h>
int main()
{
__block int total = 0;
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10000, queue, ^(size_t index) {
++total;
});
printf("total=%d\n", total);
return 0;
}
実行すれば
total=10000
と出るはずです。実行してみましょう!
total=6749
あれ。あ、ちなみにCore 2 DuoなMacBook Proで実行してますよ。もう一度。
total=10000
期待通り。念のためもう一回。
total=8664
うーん。ということで、すでにお気づきのことと思いますが、
__block変数はスレッドセーフではありません
その1から読んでくださっている読者の方には当然の結果かとおもいます。clang -rewrite-objcで見たとおり、
++(total.__forwarding->total);
になってるだけですから、スレッドセーフなわけがないのです。マルチスレッド下で、__block変数を安全に更新する方法とははたして!? つづきます。