4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

スレッド完全に理解した

Last updated at Posted at 2025-11-30

はじめに

アプリ開発を行っていると、「スレッド」という単語が頻繁に登場します。
でも、「スレッドって何?」と聞かれると、意外とうまく説明できなかったりします。

この記事では、スレッドという仕組みを基礎から順番に説明していきます。
ハードウェアの知識がなくても大丈夫なように書いていくので、安心してください(?)。

一部Swiftが出てきますが、メインテーマは「スレッド」です。

🍴 身近な例から考えてみる

スレッドを理解するために、まずは料理をする場面を想像してみましょう。

あなたがキッチンで一匹で料理をしているとき、できることは一つずつです。
野菜を切りながら同時に鍋をかき混ぜることはできません。
これがシングルスレッドの状態です。

でも、もう一匹手伝ってくれる猫がいたらどうでしょう?

あなたが野菜を切っている間に、その猫が鍋をかき混ぜられます。
二つの作業が同時進行できるわけです。これがマルチスレッドのイメージです。

ここで大事なのは、「同時に作業できる数は、猫の数で決まる」ということです。

これがスレッドを理解する第一歩です😺

スクリーンショット 2025-11-30 18.46.27.png

Gemini:「このイラストかわいいやろ」

スレッドには3種類ある

実は、「スレッド」という言葉は文脈によって3つの異なる意味で使われます。これが混乱の元なので、最初に整理しておきましょう。

1. ハードウェアスレッド

CPUが物理的に持っている、同時実行できる数のこと。
「4コア8スレッドCPU」と言ったときの「8スレッド」がこれです。

2. OSスレッド(カーネルスレッド)

オペレーティングシステムが管理する実行単位。
私たちがプログラムで「スレッドを作る」と言ったときは、通常これを指します。

3. ユーザースレッド(グリーンスレッド)

プログラムのランタイムやライブラリが管理する実行単位。
OSからは見えません。

この記事では主にOSスレッドについて説明していきますが、まずはハードウェアの仕組みから理解していきましょう。

CPUの物理的な構造を理解する

コンピュータのハードウェアについて少しだけ説明します。

CPUコアって何?

CPUコアは、実際に計算処理を行うハードウェアの部品です。先ほどの料理の例で言うと、「実際に手を動かせる人」がコアです。

例えば「4コアCPU」と言われたら、「同時に4つの作業ができる人が4人いる」と考えてください。

ハードウェアスレッドって何?

一部のCPUにはハードウェアスレッドという機能があります(Intelの「Hyper-Threading」が有名です)。

これは、1つのコアが2つの作業を素早く切り替えながらこなす技術です。完全な同時実行ではありませんが、効率よく処理できます。

「4コア8スレッドCPU」なら、「4人の作業員がいて、それぞれが2つの作業を並行してこなせる」というイメージです。理論上、最大8つの処理が同時に進められます。

ここで覚えておいてほしいのは、「物理的に同時実行できる数には限界がある」ということです。

OSスレッドという仕組み

さて、ここからが本題です!

私たちがプログラムで「スレッドを作る」と言うとき、それはOSスレッドのことを指します。
これは、CPUのハードウェアスレッドとは別物なんです。

OSスレッドって何をしているの?

OSスレッドは、オペレーティングシステムが管理する実行の単位です。

もう少し正確に言うと、OSスレッドは「CPUに実行してもらう命令の流れ」を表す単位です。プログラムのコードは、必ずどこかのOSスレッド上で実行されています。

各OSスレッドは、以下のような情報を持っています。

  • レジスタの状態 - 現在どんな計算をしているかの情報
  • スタック領域 - そのスレッド専用の作業メモリ(数百KB〜数MB)
  • スレッドID - OSスレッドを識別するための番号
  • 実行状態 - 今実行中なのか、待機中なのか、など
  • プログラムカウンタ - 次にどの命令を実行するかを示す情報

プログラムのコードは複数のOSスレッドで共有されますが、それぞれのOSスレッドは独自の「作業スペース」を持っているわけです。

重要なポイントは以下の3つです。

  • OSスレッドは、コードを順番に実行していく「実行の流れ」を表す
  • 一つのアプリ(プロセス)の中に、複数のOSスレッドを作ることができる
  • 最終的にコードを実行するのは、常にCPUのコア

つまり、あなたが書いたコードは、必ずどこかのOSスレッドによって実行されているということです。

OSスレッドはいくつでも作れる?

ここが重要なポイントです!

OSスレッドは、ハードウェアスレッドの数を超えて作成できます。例えば、8ハードウェアスレッドのCPUでも、100個のOSスレッドを作ることは可能です。

「あれ?同時に実行できるのは8つまでじゃないの?」と思いますよね。その通りです。

ここで登場するのがスケジューラという仕組みです。

スケジューラの役割

スケジューラは、OSの中にいる「作業の割り振り係」のようなものです。

たくさんのOSスレッドがある場合、スケジューラは次のように動きます。

  1. 実行したいOSスレッドがたくさんある
  2. でも、同時に実行できるのは限られた数(ハードウェアスレッド数)だけ
  3. スケジューラが「次はこのOSスレッドを実行しよう」と決める
  4. 一定時間実行したら、別のOSスレッドに切り替える
  5. これを繰り返す

つまり、多数のOSスレッドを高速に切り替えながら、あたかも同時に動いているかのように見せているわけです。

この切り替え作業をコンテキストスイッチと呼びます。

コンテキストスイッチのコスト

コンテキストスイッチは便利な仕組みですが、タダではありません。

OSスレッドを切り替えるとき、OSは以下のような作業をする必要があります。

  1. 現在のOSスレッドの状態を保存 - レジスタの内容をメモリに書き出す
  2. 次のOSスレッドの状態を読み込む - メモリから別のOSスレッドの情報を読み出す
  3. CPUのキャッシュがリセットされる - 高速メモリの中身が無効になる
  4. 実行を再開 - プログラムカウンタを復元して処理を続ける

この一連の処理には時間がかかります。特に、CPUキャッシュがリセットされるのが痛いです

キャッシュとは、CPUがよく使うデータを一時的に保存しておく高速メモリのこと。これが無効になると、メモリから再度データを読み込む必要があり、処理が遅くなります。

なぜOSスレッドを増やしすぎると遅くなるのか

ここまで読めば、「OSスレッドを増やしすぎると遅くなる」という話の理由がわかるはずです。

例えば、8ハードウェアスレッドのCPUで1000個のOSスレッドを動かそうとすると、どうなるでしょう?

  • ほとんどのOSスレッドは待機状態になる
  • OSは頻繁にコンテキストスイッチを行う必要がある
  • 切り替えのコストばかりかかって、実際の処理が進まない

つまり、作業員が多すぎて引き継ぎばかりしている状態になるわけです。これでは効率が悪いですよね。

OSスレッドのコストまとめ

OSスレッドは「軽量」と言われることもありますが、実際には以下のようなコストがあります。

  • 生成コスト - OSがOSスレッドを作る処理には時間がかかる
  • メモリコスト - 各OSスレッドがスタック領域(数百KB〜数MB)を消費する
  • 切り替えコスト - コンテキストスイッチには確実に時間がかかる
  • キャッシュミス - 切り替えのたびにCPUキャッシュが無効になる
  • スケジューリングコスト - OSがOSスレッドを管理する処理自体にも負荷がある

だから、無制限にOSスレッドを作ることはできないし、作るべきでもないのです。

スレッドプールという解決策💡

OSスレッドの生成コストを避けるために、多くのシステムはスレッドプールという仕組みを使っています。

スレッドプールの仕組み

スレッドプールは、こんな風に動きます。

  1. 事前準備 - アプリ起動時に、あらかじめ一定数のOSスレッドを作っておく
  2. タスクの割り当て - 実行したい処理が来たら、空いているOSスレッドに渡す
  3. 再利用 - 処理が終わってもOSスレッドは破棄せず、次の処理を待つ
  4. 動的調整 - 必要に応じてOSスレッド数を増やしたり減らしたりする

これによって、以下のメリットが得られます

  • OSスレッドを毎回作る手間が省ける
  • 同時実行するOSスレッド数をコントロールできる
  • CPU使用率を適切に保てる
  • システム全体の効率が上がる

🍽️ レストランのホールスタッフを想像してみましょう!

お客さんが来るたびに新しいスタッフを雇って、帰ったら解雇する、なんてことはしませんよね。あらかじめ必要な人数を確保しておいて、お客さんに対応してもらう。それと同じ考え方です。

ユーザースレッドという仕組み

OSスレッドとは別に、ユーザースレッド(グリーンスレッドとも呼ばれます)という仕組みもあります。これは少し応用的な話ですが、知っておくと理解が深まります。

ユーザースレッドとは

ユーザースレッドは、プログラムのランタイム(実行環境)やライブラリが管理する実行単位です。

ユーザースレッドの特徴は以下の通りです。

  • ライブラリやランタイムが管理する
  • OSから見えるOSスレッド数は増えない
  • 切り替えをライブラリが制御できる
  • コンテキストスイッチのコストが低い

例えば、100個のユーザースレッドがあっても、実際のOSスレッドは8個だけ、ということができます。

OSスレッドとユーザースレッドの違い

整理すると、こんな感じです

OSスレッド(カーネルスレッド)

  • OSが直接管理する
  • コンテキストスイッチもOSが行う
  • Swiftのpthreadがこのタイプ
  • 生成・切り替えのコストが高い

ユーザースレッド

  • ライブラリやランタイムが管理する
  • OSから見えない
  • 切り替えコストが低い

Swift Concurrencyの仕組みも、このユーザースレッド的な動作を取り入れています。でも、この記事の主題は「スレッドそのもの」なので、詳細は省略します。

Swiftでスレッドはどう見えるか

Swiftは、OSスレッドを直接意識しなくても済むように設計されています。でも、実際にはあなたのコードは必ずどこかのOSスレッド上で動いています。

SwiftでOSスレッドが「見える」ポイントは、こんなところです

  • Thread.currentを使うと、現在どのOSスレッドで実行されているか確認できる
  • MainActorのコードは、必ずメインスレッド(特定のOSスレッド)上で実行される
  • バックグラウンド処理は、OSのスレッドプールで実行される
  • 非同期処理(async/await)では、再開時に別のOSスレッドになることがある

つまり、Swiftの高レベルな仕組み(async/awaitなど)は、このOSスレッドという土台の上に構築されているわけです

まとめ

長くなりましたが、スレッドについて整理してみましょう。

スレッドの整理

3種類のスレッドを理解する

  • ハードウェアスレッド - CPUが物理的に持つ同時実行数
  • OSスレッド - OSが管理する実行単位(私たちが普段扱うスレッド)
  • ユーザースレッド - ライブラリが管理する軽量な実行単位

ハードウェアとソフトウェアの関係

  • CPUコアは物理的な実行ユニット
  • ハードウェアスレッドは1コアで複数処理を扱う技術
  • OSスレッドはハードウェアスレッド数を超えて作成できる
  • スケジューラがOSスレッドを切り替えながら実行する

コストと効率

  • コンテキストスイッチには確実にコストがかかる
  • OSスレッドを増やしすぎると逆に遅くなる
  • スレッドプールで効率化できる
  • 適切なOSスレッド数を保つことが重要

OSスレッドの仕組みを理解すると、「なぜメインスレッドをブロックしてはいけないのか」「なぜasync/awaitが便利なのか」といったことが、より深く理解できるようになります。

アプリのパフォーマンスや設計を考える上で、この知識はきっと役に立つはずです。

ここまで読んでいただき、ありがとうございました😺

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?