Cプログラミング
 Computer >> コンピューター >  >> プログラミング >> Cプログラミング

【C言語】pthread_cancel()関数の使い方 – スレッドのキャンセル方法を解説

POSIXスレッド(pthread)プログラミングにおいて、pthread_cancel()関数は、指定したスレッドIDに対応する特定のスレッドをキャンセル(終了要求)するために使用されます。この関数は、対象のスレッドに対してキャンセル要求を送信し、スレッドの終了を促します。

pthread_cancel()の構文

pthread_cancel()の基本的な構文は以下のとおりです。

int pthread_cancel(pthread_t th);

引数には、キャンセルしたいスレッドのスレッドID(pthread_t型)を指定します。戻り値としては、成功した場合に0が返され、失敗した場合にはエラーコードが返されます。

サンプルコード:スレッドをキャンセルする方法

それでは、実際にpthread_cancel()を使ってスレッドをキャンセルする例を見てみましょう。以下のプログラムでは、2つのスレッドを作成し、スレッド1がカウンタの値が5になった時点でスレッド2に対してキャンセル要求を送り、その後自身も終了します。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>

int count = 0;
pthread_t sample_thread;

void* thread_one_func(void* p) {
    while (1) {
        printf("This is thread 1\n");
        sleep(1); // 1秒間待機
        count++;
        if (count == 5) {
            // カウンタが5になったら、スレッド2にキャンセル要求を送り、
            // 現在のスレッド自身も終了する
            pthread_cancel(sample_thread);
            pthread_exit(NULL);
        }
    }
}

void* thread_two_func(void* p) {
    sample_thread = pthread_self(); // スレッド2のIDを保存
    while (1) {
        printf("This is thread 2\n");
        sleep(2); // 2秒間待機
    }
}

main() {
    pthread_t t1, t2;
    // 2つのスレッドを作成
    pthread_create(&t1, NULL, thread_one_func, NULL);
    pthread_create(&t2, NULL, thread_two_func, NULL);
    // スレッドの完了を待機
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
}

コードのポイント

  • スレッドIDの保存: thread_two_func()内でpthread_self()を使い、自分自身のスレッドIDをグローバル変数sample_threadに保存しています。
  • キャンセル要求: スレッド1はcountが5に達すると、pthread_cancel(sample_thread)を呼び出してスレッド2をキャンセルします。
  • スレッドの終了: キャンセル要求の送信後、スレッド1自身もpthread_exit(NULL)で終了します。

実行結果

このプログラムを実行すると、以下のような出力が得られます。

This is thread 2
This is thread 1
This is thread 1
This is thread 2
This is thread 1
This is thread 1
This is thread 1
This is thread 2
This is thread 2
This is thread 2
This is thread 2
This is thread 2
This is thread 2
This is thread 2
This is thread 2
This is thread 2
This is thread 2
This is thread 2
This is thread 2

出力の解説

一見すると、スレッド1が終了した後も「This is thread 2」が表示され続けているように見えます。これは、pthread_cancel()によるキャンセル処理のタイミングや、スレッドのキャンセルタイプ(遅延キャンセルがデフォルト)によって、キャンセル要求がすぐに反映されない場合があるためです。スレッド2はsleep(2)中にキャンセルポイントに入るため、実際の動作は環境によって異なることがあります。

注意点

  • pthread_cancel()はデフォルトでは遅延キャンセル(deferred cancellation)として動作し、対象スレッドがキャンセルポイント(sleep()read()など)に到達したときに初めて終了します。
  • リソースの解放漏れを防ぐため、キャンセルされる可能性のあるスレッドではクリーンアップハンドラ(pthread_cleanup_push() / pthread_cleanup_pop())の利用を検討しましょう。
  • スレッドのキャンセルはデッドロックやリソースリークの原因になりやすいため、設計段階で慎重に扱うことが推奨されます。
  1. C#でスレッドを強制終了する方法|フラグ変数を使った安全な終了手法

    C#で実行中のスレッドを終了させたい場合、かつては Thread.Abort() メソッドが使われていましたが、現在は非推奨となっています(.NET Core 以降ではサポートされていません)。代わりに、bool型のフラグ変数を活用して、スレッドの処理を安全に停止させる方法が一般的です。 この記事では、フラグ変数と Thread.Join() を組み合わせて、実行中のスレッドを確実に終了させる方法をサンプルコード付きで解説します。 1. スレッドを作成して開始する まず、新しいスレッドを作成し、開始します。 // 新しいスレッドを作成 Thread thread = new Thread(c.

  2. Javaのスレッドプールとは?仕組みと実装例をわかりやすく解説

    スレッドプールとはスレッドプール(Thread Pool)とは、あらかじめ初期化された複数のスレッドをまとめて管理する仕組みのことです。基本的な考え方は、アプリケーションの起動時に一定数のスレッドを作成してプールに入れておき、それらのスレッドが仕事を待機するというものです。サーバーがリクエストを受け取ると、利用可能なスレッドがあればプールから1つ取り出して処理を任せます。スレッドはタスクの完了後、破棄されることなくプールへ戻り、次の仕事を待ちます。もしプール内に空きスレッドが存在しない場合は、空きができるまでサーバー側で待機することになります。スレッドプールのメリットタスクごとに新しいスレッド