C言語でPOSIXセマフォを使用する方法【初心者向け解説】
セマフォ(semaphore)は、プロセスやスレッドの同期を実現するための重要な概念です。本記事では、実際のC言語プログラムでPOSIXセマフォをどのように使用するのかを、サンプルコードと実行結果を交えて解説します。
POSIXセマフォとは
セマフォは、複数のプロセスやスレッドが共有リソースに同時にアクセスすることを防ぎ、排他制御や同期を実現するための仕組みです。クリティカルセクション(同時に実行してはいけない処理領域)へのアクセスを制御する際によく使われます。
準備:ヘッダーファイルとコンパイル方法
Linuxシステムでは、POSIXセマフォライブラリを利用できます。使用するには、まず semaphore.h ヘッダーファイルをインクルードします。コンパイル時には、以下のように pthread と rt ライブラリをリンクするオプションを指定します。
gcc program_name.c -lpthread -lrt
主なセマフォ関数
POSIXセマフォでよく使われる関数は以下の通りです。
- sem_init():名前なしセマフォを初期化します(スレッド間同期用)
- sem_open():名前付きセマフォを作成・オープンします(プロセス間通信(IPC)用)
- sem_wait():セマフォの値を減らしてロックを取得します。値が0の場合は待機状態になります
- sem_post():セマフォの値を増やしてロックを解放します
- sem_destroy():使用済みのセマフォを破棄します
サンプルコード
以下は、2つのスレッドがセマフォを使ってクリティカルセクションへのアクセスを制御する例です。
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_t mutex;
void* thread(void* arg) { // スレッドとして動作する関数
sem_wait(&mutex); // 待機状態(ロック取得)
printf("\nEntered into the Critical Section..\n");
sleep(3); // クリティカルセクション
printf("\nCompleted...\n"); // クリティカルセクションから退出
sem_post(&mutex); // ロック解放
}
main() {
sem_init(&mutex, 0, 1); // セマフォを初期値1で初期化
pthread_t th1,th2;
pthread_create(&th1,NULL,thread,NULL);
sleep(2);
pthread_create(&th2,NULL,thread,NULL);
// メインスレッドで各スレッドの終了を待つ
pthread_join(th1,NULL);
pthread_join(th2,NULL);
sem_destroy(&mutex); // セマフォを破棄
}
コードのポイント
sem_init(&mutex, 0, 1) の第2引数が 0 の場合、セマフォは同一プロセス内のスレッド間で共有されます。初期値を 1 にすることで、バイナリセマフォ(ミューテックスのような動作)として機能し、1つのスレッドだけがクリティカルセクションに入れるようになります。
1つ目のスレッドが sem_wait() でロックを取得すると、2つ目のスレッドは sem_post() でロックが解放されるまで待機します。そのため、2つのスレッドのクリティカルセクション処理が重なることはありません。
実行結果
soumyadeep@soumyadeep-VirtualBox:~/Cpp_progs$ gcc 1270.posix_semaphore.c -lpthread -lrt
1270.posix_semaphore.c:19:1: warning: return type defaults to 'int' [-Wimplicit-int]
main() {
^~~~
soumyadeep@soumyadeep-VirtualBox:~/Cpp_progs$ ./a.out
Entered into the Critical Section..
Completed...
Entered into the Critical Section..
Completed...
soumyadeep@soumyadeep-VirtualBox:~/Cpp_progs$
実行結果を見ると、1つ目のスレッドがクリティカルセクションに入り、処理を完了してから2つ目のスレッドが入っていることが分かります。なお、main() の戻り値の型が省略されているため警告が表示されていますが、動作には問題ありません。本番のコードでは int main(void) と記述し、return 0; を返すのが望ましいでしょう。
まとめ
POSIXセマフォを使うことで、スレッド間の排他制御を簡単に実装できます。基本的な流れは「sem_init() で初期化 → sem_wait() でロック取得 → クリティカルセクション実行 → sem_post() でロック解放 → sem_destroy() で破棄」となります。マルチスレッドプログラミングにおける競合状態(race condition)を防ぐために、ぜひ活用してみてください。
-
GoogleスプレッドシートでGoogle翻訳を使う方法!GOOGLETRANSLATE関数の基本と応用
Google翻訳は、新しい言語を学ぶときにとても便利なツールです。Google翻訳アプリでは、言語の自動判別や、カメラを使って看板の文字を翻訳するなど、さまざまな機能が利用できます。実は、GoogleスプレッドシートでもGoogle翻訳の機能を使うことができます。セルに簡単な関数を入力するだけで、あらゆる言語を別の言語に翻訳できるのです。ここでは、その具体的な方法をわかりやすく解説します。Googleスプレッドシートで任意の言語を翻訳するGoogle翻訳機能を使うには、まずGoogleスプレッドシートを開き、翻訳したい言葉を任意のセルに入力します。例として、セルA1に「cat」という単語を入力
-
Rubyスレッドの使い方を徹底解説!初心者向けわかりやすいチュートリアル
Rubyにおけるスレッド(Thread)とは、プログラムの中で複数の処理を同時に実行するための仕組みです。スレッドを活用すれば、Rubyプログラムは複数のタスクを並行してこなせるようになり、全体の処理速度向上が期待できます。 具体的には、次のような場面で役立ちます。 複数のファイルを同時に読み込む 複数のWebリクエストを同時に処理する 複数のAPIへ同時に接続する スレッドを使ったプログラムは「マルチスレッド」と呼ばれ、作業をより速く完了できるようになります。 ただし、注意点がひとつあります。 MRI(Matzs Ruby Interpreter)と呼ばれる標準のRuby処理系では、I/