「スレッドセーフ」の版間の差分

提供: C言語入門
移動: 案内検索
(スレッドセーフであるかの判断基準)
行21: 行21:
 
* volatile 変数を利用していない
 
* volatile 変数を利用していない
 
* [[スレッドセーフ]]でない関数を呼び出していない
 
* [[スレッドセーフ]]でない関数を呼び出していない
 
 
== スレッドセーフの要件 ==
 
== スレッドセーフの要件 ==
 
[[スレッドセーフ]]を実現する方法として、以下の要件があります。
 
[[スレッドセーフ]]を実現する方法として、以下の要件があります。
行28: 行27:
 
* スレッドローカルデータ
 
* スレッドローカルデータ
 
* [[アトミック]]操作
 
* [[アトミック]]操作
== 排他制御 ==
+
=== リエントラント ===
 +
関数をリエントラント(reentrant, 再入可能)にすることで、[[スレッドセーフ]]となります。
 +
=== 排他制御 ===
 +
'''排他制御'''により、'''共有データ'''へのアクセスを '''逐次化''' することで、[[スレッドセーフ]] となります。複数の共有データにアクセスする場合には、'''ロック''' のやり方('''排他制御''')を十分に注意して行う必要があります。
 +
=== スレッドローカルデータ ===
 +
スレッドの識別子をキーにし、グローバル変数を'''スレッド'''毎に持たせることで、サブルーチン間(関数間)を超える範囲で変数を利用できます。各変数にアクセスするサブルーチン(関数)は、'''リエントラント'''ではありません。
 +
=== アトミック操作 ===
 +
共有データへのアクセスを '''アトミック'''操作にすることで、他のスレッドからの同時アクセスがおきないことを保証します。
 +
== 実装 ==
 +
=== 排他制御 ===
 
[[pthread]] を利用する場合の排他制御には、pthread_mutex を利用できます。
 
[[pthread]] を利用する場合の排他制御には、pthread_mutex を利用できます。
 
詳しくは、[[pthread_mutexで排他ロックする方法]] をご参照下さい。
 
詳しくは、[[pthread_mutexで排他ロックする方法]] をご参照下さい。
== アトミック操作 ==
+
=== アトミック操作 ===
 
C言語で[[アトミック]]な操作をする場合は、[[C11]]で導入した <u>[[アトミック]]型修飾子</u> が利用できます。
 
C言語で[[アトミック]]な操作をする場合は、[[C11]]で導入した <u>[[アトミック]]型修飾子</u> が利用できます。
 
== 関連項目 ==
 
== 関連項目 ==

2016年4月16日 (土) 18:19時点における版

スレッドセーフ (Thread-safe) とは、マルチスレッドプログラミングの概念です。複数のスレッドが同時に、同じコードを実行しても問題が発生しない、ということを意味します。

読み方

スレッドセーフ
すれっどせーふ
Thread-safe
すれっどせーふ

概要

マルチスレッドプログラミングでは、複数のスレッドが並列で実行されるため、リソースへのアクセスに注意が必要になります。 forkモデルのマルチプロセスでは、メモリ空間がプロセスごとに分離されますが、マルチスレッドプログラミングの場合は、同じメモリ空間で実行されるため、広域メモリへのアクセスを行うときに、mutex ロックを利用するなど、排他制御などが必要となります。

格スレッドから考えなしにリソースにアクセスするとき、プログラムは予期せぬ事態に陥り、期待した動作ができず、おかしな結果になったり、プログラムが停止してしまう、といったことにつながります。

マルチスレッドプログラミング では、プログラムが安全に実行できるように、 スレッドセーフ に対応したライブラリを利用することや、スレッドセーフ のコードを書く必要があります。

スレッドセーフであるかの判断基準

プログラムがスレッドセーフであるかを判断するのは、簡単ではありませんが、以下の点に着目して、コードを読む・調べることで、判断することができます。

  • グローバル変数(広域変数)やヒープ(動的メモリ)、静的変数(スタティック変数,static変数)にアクセスしていない
  • ファイルやプロセスなどのリソースの確保や開放を実施していない
  • 参照やポインタによる間接的なアクセスをしていない
  • volatile 変数を利用していない
  • スレッドセーフでない関数を呼び出していない

スレッドセーフの要件

スレッドセーフを実現する方法として、以下の要件があります。

  • リエントラント
  • 排他制御
  • スレッドローカルデータ
  • アトミック操作

リエントラント

関数をリエントラント(reentrant, 再入可能)にすることで、スレッドセーフとなります。

排他制御

排他制御により、共有データへのアクセスを 逐次化 することで、スレッドセーフ となります。複数の共有データにアクセスする場合には、ロック のやり方(排他制御)を十分に注意して行う必要があります。

スレッドローカルデータ

スレッドの識別子をキーにし、グローバル変数をスレッド毎に持たせることで、サブルーチン間(関数間)を超える範囲で変数を利用できます。各変数にアクセスするサブルーチン(関数)は、リエントラントではありません。

アトミック操作

共有データへのアクセスを アトミック操作にすることで、他のスレッドからの同時アクセスがおきないことを保証します。

実装

排他制御

pthread を利用する場合の排他制御には、pthread_mutex を利用できます。 詳しくは、pthread_mutexで排他ロックする方法 をご参照下さい。

アトミック操作

C言語でアトミックな操作をする場合は、C11で導入した アトミック型修飾子 が利用できます。

関連項目