マルチスレッドのプログラミング

マルチスレッドアプリケーションのコンパイル

この節では、Sun Studio C コンパイラを使用してマルチスレッドプログラムをコンパイルする方法について説明します。 Sun Studio C コンパイラは並列プログラミング向けに最適化されており、ほかの C コンパイラにない多くの機能を備えています。C コンパイラの詳細については、『Sun Studio 12: C ユーザーズガイド』を参照してください。

コンパイルの準備

アプリケーションは、Solaris スレッドの場合は <thread.h> を、POSIX スレッドの場合は <pthread.h> をインクルードする必要があります。使用している API に対応するファイルか、またはアプリケーションが両方のスレッドの API を使用している場合は両方のファイルをインクルードするようにしてください。詳細は、pthread.h(3HEAD) のマニュアルページを参照してください。アプリケーションはまた、<errno.h><limits.h><signal.h><unistd.h> ファイルもインクルードする必要があります。

スレッドの選択 — Solaris または POSIX

Solaris での pthread の実装は、Solaris スレッドと完全に互換性があります。同じアプリケーションで Solaris スレッドと pthread の両方を使用できます。各スレッド実装の相違点については、pthreads(5) のマニュアルページを参照してください。また、相違点については、このマニュアルの第 6 章Solaris スレッドを使ったプログラミングも参照してください。

スレッドの相違点の 1 つに、fork 関数の動作があります。

Solaris 9 リリースでは、fork() 関数の動作は、アプリケーションが POSIX スレッドライブラリにリンクされているかどうかによって決定されていました。-lthread (Solaris スレッド) にリンクされ、-lpthread (POSIX スレッド) にリンクされていない場合は、fork() によって、親プロセスのすべてのスレッドが子スレッド内に複製されました。アプリケーションが -lpthread にリンクされている場合は、-lthread にもリンクされかどうかには関係なく、fork()fork1() と同じであり、呼び出しスレッドのみが複製されました。

Solaris 10 リリースからは、forkall() 関数の呼び出しによって、親プロセスのすべてのスレッドが子プロセス内に複製されるようになりました。fork1() の呼び出しによって、呼び出しスレッドのみが子プロセス内に複製されます。Solaris 10 リリースでは、fork() の呼び出しは fork1() の呼び出しと等価です。つまり、呼び出しスレッドのみが子プロセス内に複製されます。これが、fork() に対して POSIX で規定されている動作です。アプリケーションで、すべての fork セマンティクスを複製する必要がある場合は、forkall() を呼び出してください。

<thread.h> または <pthread.h>

インクルードファイル <thread.h> には、Solaris スレッドの関数の宣言が含まれています。Solaris スレッドの任意の関数を呼び出すには、プログラムで <thread.h> をインクルードする必要があります。このファイルを使用すると、以前の Solaris ソフトウェアのリリースと互換性のあるコンパイルされたコードを生成できます。

インクルードファイル <pthread.h> は pthread の関数の宣言を含んでおり、プログラムで pthread を使用する場合に必要になります。

アプリケーションで <thread.h><pthread.h> の両方をインクルードすることによって、同じアプリケーション内に Solaris スレッドと POSIX スレッドを混在させることができます。その場合は、リンクおよびコンパイル時に、pthread の API でリンクするための -lpthread フラグを指定する必要があります。

-mt を使用した場合は、Solaris スレッドの API が自動的にリンクされます。-lthread を明示的に指定する代わりに、常に -mt オプションを使用してください。pthread を使用するには、リンクのコマンド行で -mt オプションと -lpthread オプションを指定します。libpthread ライブラリによって libthread へのインタフェースが提供されるため、pthread を使用する場合も libthread が引き続き必要です。

マルチスレッドプログラムのコンパイルとリンク

Sun Studio C コンパイラ (cc) には、マルチスレッドコードのコンパイルとリンクを行うための -mt オプションが用意されています。-mt オプションは、ライブラリの適切な順序でのリンクを保証するものです。

-mt オプションは、一貫性をもって使用する必要があります。-mt でのコンパイルとリンクを別のステップで行う場合は、リンクステップとコンパイルステップで -mt オプションを使用する必要があります。1 つの変換ユニットを -mt でコンパイルおよびリンクする場合は、そのプログラムのすべてのユニットを -mt でコンパイルおよびリンクする必要があります。

Solaris 10 リリースと Solaris 9 リリースのコンパイルとリンクには同じコマンドを使用できますが、次のいくつかの相違点を考慮するようにしてください。

POSIX スレッド環境でのコンパイルとリンク

アプリケーションで pthread のみを使用するか、または Solaris スレッドと pthread の両方を使用している場合は、次のコマンドを使用してコンパイルとリンクを行います。


cc -mt [ flag ... ] file... [ library... ] -lpthread 

-mt オプションが libthread ライブラリにリンクするに対して、-lpthread オプションは libpthread ライブラリにリンクします。libpthread によって libthread へのインタフェースが提供されるため、pthread を使用する場合は両方のフラグが必要です。

-mt オプションは、コマンド行の任意の場所に指定できます。-lpthread オプションは、ユーザーライブラリのあとに指定するようにします。-mt-lpthread の相対位置は関係ありません。

たとえば、次の行はすべて等価です。

cc -mt -o myprog f1.o f2.o   -lmylib -lpthread
cc     -o myprog f1.o f2.o -mt -lmylib -lpthread
cc     -o myprog f1.o f2.o -lmylib -mt -lpthread
cc     -o myprog f1.o f2.o -lmylib -lpthread -mt

cc コマンドのオプションの詳細については、Sun Studio cc(1) のマニュアルページおよび『Sun Studio 12: C ユーザーズガイド』を参照してください。

Solaris スレッド環境でのコンパイルとリンク

Solaris スレッド環境では、アプリケーションのコンパイルとリンク時に、次のオプションを指定します。

アプリケーションで Solaris スレッドのみを使用している場合は、次のコマンドを使用してコンパイルとリンクを行います。


cc -mt [ flag ... ] file... [ library... ]

-mt オプションは、libthread ライブラリにリンクします。

cc コマンドのオプションの詳細については、Sun Studio cc(1) のマニュアルページおよび『Sun Studio 12: C ユーザーズガイド』を参照してください。

混在スレッド環境でのコンパイルとリンク

アプリケーションで pthread と Solaris スレッドの両方の関数を使用している場合は、pthread のみのコンパイルに使用したものと同じコマンドでコンパイルとリンクを行うことができます。


cc -mt [ flag ... ] file... [ library... ] -lpthread 

混用の場合は、thread.hpthread.h の両方を組み込む必要があります。

リンク時の POSIX セマフォー用 -lrt の指定

Solaris セマフォールーチン sema_*(3C) は、標準 C ライブラリに入っています。これに対して、「セマフォーによる同期」で説明されているように、標準 sem_*(3RT) POSIX セマフォールーチンを取得するには、リンク時に -lrt ライブラリを指定します。