Tech`s Report

MENU

【初心者向け】スレッドセーフとは〜わかりやすく解説

フリーエンジニア向け案件を紹介【BTCエージェント】

システムエンジニアで特にフロント系のシステムを開発している方は「スレッドセーフ」は絶対に知ってなければいけません。
なぜかというとスレッドセーフの考え方を知らないでコーディングすると大障害に繋がるからです。
そしてたちが悪いのがスレッドセーフはなかなかテストで見つけずらいので、コーディング担当者が正しい知識をもって開発することが重要になってきます。

今回スレッドセーフについてわかりやすく解説していきますので

  • スレッドセーフってそもそもよくわからない
  • 重要なのは知っているけどなんとなくしかわからない

という方は是非最後まで読んでみてください。
 

スレッドセーフとは

一言でいうと マルチスレッドでも問題なく動作するプログラムのことを表します。
要は同時に複数の人がアクセスしても問題なく動作するシステムであるか?ということです。
Amazonのネットショッピングなどは何万人という人がアクセスしても問題なく動作しますよね。

このように複数の人が同時にアクセスをすることを前提にシステムは作られています。
これをスレッドセーフのシステムといいます。

では、正しいシステムの動きと、正しくないシステムの動きを具体例や図も交えて確認していきましょう。
 

スレッドセーフのシステム

スレッドセーフのシステムのマルチスレッド状況下の動作の具体例を記載します。
 
通常の会員WEBサイトあるとします。
全く同タイミングで2人からアクセスがあったときの【動作】と【結果】を以下に記載します。

<Aさん>

【動作】Aさんがアクセスして会員情報を照会

【結果】Aさんの情報が表示される

<Bさん>

【動作】Bさんがアクセスして自分の情報を照会

【結果】Bさんの情報が表示される

上記はそれぞれ自分の情報が照会できているため問題ありませんね。 これをマルチスレッドでも問題がなく動作するといいます。
つまり複数の人が同時にアクセスしても、プログラムがそれぞれの人(スレッド)単位で情報を保持して動作する
ということです。  
 

アンスレッドセーフのシステム

では、アンスレッドセーフ、すなわちスレッドセーフでないシステムのマルチスレッド状況下の動作を以下に記載します。

<Aさん>

【動作】Aさんがアクセスして会員情報を照会

【結果】Bさんの情報が表示される

<Bさん>

【動作】Bさんがアクセスして自分の情報を照会

【結果】Bさんの情報が表示される

Aさんが照会した画面にBさんの会員情報が表示されてしまいましたね。 これがスレッドセーフでないシステムになります。
この場合個人情報漏洩となり、企業の信用を失い兼ねない事故となります。

また、上記事象はたった1行のコーディングミスで発生してしまいます。

 

マルチスレッドで動作不良が起こる原因

マルチスレッドでないシステムがどのような状態になっていたか下図に示します。

f:id:TechnologyShare:20200330173418p:plain

 
図の説明をします。


  1. Aさんが自身の会員情報の要求をする
  2. 会員サイトがAさんの情報を取得し、メモリ上に保存
  3. Bさんが自身の会員情報の要求をする
  4. 会員サイトがBさんの情報を取得し、メモリ上に保存(★ここで上書き
  5. AさんにBさんの会員情報を返却する
  6. Aさんの画面上にBさんの会員情報が表示される

 
このように同タイミング(僅差)でアクセスがあった際に、図のようにAさんに他人の情報を表示する事象が発生してしまうんですよね。

本来、4のタイミングで上書きするのではなく、メモリをスレッド(アクセス)ごとに保存するようにしなければなりません。

実はメモリの保存場所は、「全スレッドで共有する保管場所」と「スレッドごとに保管する場所」があります。

この図では スレッドごとに保存すべき情報を、全スレッドで共有する保管場所に保存してしまった のが情報漏洩した原因になります。

なので、このように扱う情報に応じて、どのメモリを使うのかコーディングの時に意識することが非常に大切になってきます。
 

メモリの考え方

最後にスレッドセーフを技術的に理解するために、メモリの概念について説明します。(主にJavaのメモリの考え方になります。他の言語でも表現が違うだけで概念は同じなのでぜひご参照ください)

ヒープ領域とスタック領域

スレッドセーフにおけるメモリを理解するにあたりこの「ヒープ領域」と「スタック領域」は理解しておきましょう。

下図をご参照ください。

f:id:TechnologyShare:20200330200535p:plain

  • ヒープ領域は全スレッドで共有して使用する空間になります。
  • スタック領域はスレッドごとに固有の空間になります。

なので、定数や共通処理などはヒープ領域に展開することでシステムのメモリの利用効率が上がります。
ただ、個人情報などをデータベースから取得した際は必ずスタック領域に保存するようにしないといけません。

重大な事故を防ぐためには基本はスタック領域で管理し、特別な意思がある場合はヒープ領域を使用するくらいの心構えの方がいいと思います。
昨今サーバのスペックも上がってきており、そこまで一生懸命ヒープ領域を使用する必要もなくなってきてます。

 

正しいメモリの使い方

ヒープ領域とスタック領域にそれぞれどういう情報を保存するのか具体例を示します。

f:id:TechnologyShare:20200330201630p:plain

例えば会員がログインした後のページのタイトルの文言(TITLE=通販サイト)は、全ユーザー共通の文言のため、スレッドごとに管理せずに、ヒープ領域で管理した方がいいですよね。
ヒープ領域で管理することで、各スレッド領域にでいちいち「TITLE=通販サイト」のような保存処理が不要になります。 逆に名前や誕生日などの個人情報は各スレッド領域で管理する必要があります。

 

最後に~スレッドセーフ メモリ管理 の重要性

スレッドセーフやメモリ管理が重要な考え方だとご理解いただけたでしょうか。

スレッドセーフのバグを見つけるのは並列処理を検証する必要があり非常に困難です。 それは並列処理のテストをするにしても、コンピュータの処理は高速のため、スリープで一時的に処理を止めるなどする必要があるからです。

また、すべての記述内容で網羅的にテストをするのには時間的にも技術的にも限界があります。

なので
コードについて一番理解している瞬間のコーディング中にスレッドセーフの実装を心掛ける

これが品質に繋がると思ってます。

少しでもスレッドセーフの考え方を理解する人が増えれば幸いです。
以上