だからプログラマーなんだってば(おぶおぶ)

9月6日金曜日、晴れ

明日の本戦を控えて、それでも出題の傾向そして対策は大事だろうとこんな時間まで Kotlin Heroes: Practice 2 と向きあっていた。

173 位まで順位を上げたけど、どうやらここらへんが限界、かなあ。三日間で合計10時間くらい突っ込んだ気がする。しかるに本戦はたったの二時間半。

ダメだ、戦える気がしない……。

* * *

仕事ではマルチスレッドでの動作により発生するバグを突き止めて対策できた。かなりすっきり。

Google が作っている JSON 解釈ライブラリーが、まさかマルチスレッド非対応なんてことはないだろうし…… などと目をそらしていた。
そもそもマルチスレッドで動くといったところで、読み込む(あるいは書き出す)処理それぞれがローカル変数だけで仕事をしていれば、排他制御なんて必要にならない。

で、実際のところ、やらかしたのは(一年ほど前の)僕自身だった。 JSON に含まれる日時文字列の解釈に使う DateFormat オブジェクトを Gson オブジェクトに渡すアダプターの「オブジェクト変数」にしていた。
そしてアダプターの read/write で DateFormat.format() や .parse() を呼び出している。

つまりあるスレッドで .parse() を呼び出している最中にスイッチしてさらに .parse() を呼び出すと、(オブジェクトを共有しているために)元のスレッドにスイッチし直したときに再開した .parse() の状態が壊れている──というわけ。

その当時、そのライブラリーがマルチスレッドで呼ばれるとはおもっていなかった…… と、まあ言い訳は見苦しいな。

こういうとき、一番単純にはオブジェクト変数の DateFormat にアクセスする際、つまり .format() や .parse() の呼び出しを synchronize して排他制御すればいい。
ただ、せっかくマルチスレッドで動くようになっているのに日付のフォーマットを処理するところで詰まるのはいかにも勿体無い。

ということで DateFormat をスレッドローカルストレージに叩き込み、スレッドごとに独立したオブジェクトを使うようにした。これで排他制御不要! すっきり!!

まあスレッドローカルストレージにアクセスするコストはかかるんだけれどね。

AtomicBoolean を使って空転させるのとどちらがパフォーマンスがよいんだろうか?
かつてのようにコアがひとつしかない状況なら、スレッドのスイッチするタイミングと .parse() の処理時間を比べて、スレッドスイッチの頻度の方がはるかに低いので AtomicBoolean による空転の方が良さそう。
しかしマルチコアでネイティブにスレッドが4本走るみたいな状況だと話が違ってくる──気がする。

まあこの辺りは考えてもどうしようもなくて計測しろ! というただそれだけの話ですよねー。

この記事が気に入ったらサポートをしてみませんか?