ブログスマートフォン用の表示で見るにょきにょきブログこの広告は、90日以上更新していないブログに表示しています。Javaマルチスレッドプログラミングは直感とかなり異なる挙動をすることが多く、非常に困難なプログラミングであることが知られている。不具合も発見しにくく、高負荷になった時にのみ再現したり極めて稀な状態になった時にのみ再現したり等、解決が困難なだけでなく不具合の発見や再現すら困難であることもある。不具合を発見してもその現象は不可解であることが多く、現象から直感で原因を見つける事は難しい。マルチスレッドプログラミングはシングルスレッドプログラミングに比べてはるかに困難で厄介者なのだ。この記事に、マルチスレッドプログラミングの困難さを少しでも回避するためのルールやお作法を載せておくことにする。・デッドロックマルチスレッドプログラミングで最もポピュラーな不具合。二人以上のユーザー(≒スレッド)がお互いのリソースのロックが解放されるのを待ち続けること。一般的にはロックを取る順序を制御し、デッドロックが起こりえないようにすることで解決する。デッドロックは不具合が発見しやすいのと割と解決しやすいのが良い所。・レースコンディション直訳すると競合状態。複数スレッドの処理のタイミングによって共有メモリの状態が不正な状態になること。マルチスレッドプログラミングではしばしば発生し、原因の特定・解決が困難。開発環境では再現せず本番環境でのみ再現するようなこともよくある厄介者。排他制御されてないことが原因。・スタベーションロック獲得までの解放待ちの時間が長すぎて処理が進まない不具合。特定のリソースを長時間専有してしまうことが原因。ロックの粒度を下げたりロックストライピングをしたり等でロックを奪い合う頻度を下げることで解決する。・フレームワークに頼る上で何度も述べたように、マルチスレッドプログラミングは困難であり、自分で気づかぬうちに不具合を仕込んでしまうことが良くある。これは上級プログラマでも同様だ。これを回避するにはマルチスレッドなプログラムを書かないことがベストだが、それが無理な場合はスレッドの管理を自分で行わず、既存のフレームワークに任せること。広く使われているフレームワークであればあるほど、不具合が仕込まれている可能性は低い。プログラマにとってシンプルに実装出来ることも多い。パッケージの中身をひと通り眺めておくこと。ここには汎用性が高く、安全で、パフォーマンスも良い優れたライブラリが揃っている。実装など行なってはならない。既存のフレームワーク、ライブラリを利用すること。目的のライブラリが探しても見つからない場合、もう一度探す事。それでも無ければ設計を見なおして、既存ライブラリを利用したシンプルな実装を目指すこと。シンプルな実装にならなければ実装しないこと。・シンプルな実装にすることを心がける上記のお作法とほぼ同義。マルチスレッドプログラミングで複雑な設計は極めて悪であることを理解すること。その設計で、どのような状況でロックやバリアを行うべきか説明出来なければ実装してはならない。共有するリソースは極限まで減らすこと。複数のリソースを適切にロック獲得・解放するプログラムを書くことを目指すなら、まずリソースの数を減らすことを目指すこと。複数ロックする場合は、デッドロックを防ぐためロックする順序を規約で決めておくこと。・適切に同期する「ここで排他制御すべきかどうかわからない。synchronized」はやってはいけない。適切な設計をして、同期する箇所を明らかにしておくこと。排他制御すべきかどうかわからないような状態に陥ったらそれまでのコードを捨てること。場合によっては設計も捨てること。マルチスレッドプログラミングに関わらずプログラミング全般の決まりごととして、自分が理解できないコードを書いてはならない。このルールはマルチスレッドプログラミングでは極めて重要だ。誰もデバッグができなくなり、作りなおすことになる。自分が理解できないコードを書いてはならない。・過剰な同期は避けるスタベーションを起こすので過剰な同期はしてはならない。過剰に同期をすると不具合発生時に原因の特定が困難になる。同期は必要最小限に止めること。逆に言えば、同期された領域内では最小限の処理しか行わないこと。・性能を測定出来るようになるマルチスレッドプログラミングとパフォーマンスは強い関係がある。性能が問題で無いなら、シングルスレッドで安全に、不正な状態が起こりえないプログラムを書くべきだ。それが無理ならマルチスレッドプログラミングに手を出すことになるが、プログラムを書くと同時に性能を測定出来るようになること。基本的な性能測定ツールは使えるようになっておくこと。マルチスレッドだからといって、動作環境の性能を向上させればプログラムの性能もリニアに向上するわけではない。場合によっては性能が劣化することさえある。システムパフォーマンスチューニング」ではプロセッサを1つから2つに増設したところ、性能が30%程度劣化した例が紹介されている。マルチスレッドとパフォーマンスは気難しい関係であり、コードや環境に変更を加えるたびに測定する必要がある。ほんの数行加えたロックで性能がひどく劣化したり、コンテキストスイッチのコストが増大したりなど劣化の要因は様々だ。アルゴリズムを使うことができないか検討すること。・ドキュメント化するマルチスレッドなプログラムを書いたら、設計をドキュメント化しておくこと。そのプログラムの部品群について、スレッドセーフならスレッドの安全性と共にスレッドセーフであると明記しておくこと。スレッドの安全性は下記の5つ。値は状態を持たないので本質的にスレッドセーフなもの。無条件スレッドセーフ値は状態を持つが、どのように使用されてもスレッドセーフなもの。条件付きスレッドセーフ値は状態を持ち、一部スレッドセーフであるが、スレッドセーフでない部分も存在するもの。スレッドセーフに使うにはユーザーが適切に同期を行う必要がある。スレッドセーフではない複数のスレッドからアクセスされることを想定していないもの。全てのメソッドを同期的に使用してもスレッドセーフにならないもの。まとめシングルスレッドプログラミングとマルチスレッドプログラミングは同じ言語であってもかなり異質なものである。したオブジェクトをロックオブジェクトとして使ってはいけない「文字列をロックオブジェクトとして利用したい」場合がある。)はてなブログをはじめよう!shawshank99さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。