2011-01-28

『iOS 4プログラミングブック』 第5章マルチスレッド 補遺 その4

そろそろ皆様のお手元にもあるのではないかと思ったりする『iOS 4プログラミングブック』。

「しかし、第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の解説



はい、宣伝させていただいてありがとうございます。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変数を安全に更新する方法とははたして!? つづきます。