UNIX環境プログラミング学習ノート(28)——マルチスレッドプログラミング(3):スレッドのキャンセル
14875 ワード
lienhua342014-11-24
1スレッドのキャンセル
1スレッドのキャンセル
pthreadはpthread_を提供します.cancel関数は、同じプロセス内の他のスレッドのキャンセルを要求するために使用されます.
#include
int pthread_cancel(pthread_t tid);
戻り値:成功した場合は0を返します.そうでない場合はエラー符号化を返します.
pthread_cancel呼び出しは、ターゲットスレッドをすぐに終了するのではなく、ターゲットスレッドにキャンセル要求を発行するだけです.呼び出しスレッドは、ターゲットスレッドの終了を待たずに実行されます.デフォルトでは、ターゲットスレッドは、ターゲットスレッドがキャンセルポイントに到達するまで、キャンセル要求が発行された後も実行されます.キャンセルポイントは、スレッドがキャンセルされたかどうかをチェックし、要求に従って動作する場所です.
スレッドキャンセルの例を見てみましょう.メインスレッドは新しいスレッドを作成し、新しいスレッドは5秒間睡眠を取ってから2を返します.プライマリスレッドは、新しいスレッドを作成してから2秒寝てpthreadを呼び出します.cancelは、新しいスレッドのキャンセルを要求します.最後に、新しいスレッドの終了ステータスを取得します.#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
void *
my_thread(void *arg)
{
int i=0;
printf("[new thread]: I will sleep 5 seconds.
");
while (i < 5) {
sleep(1);
i = i + 1;
printf("[new thread]: %d
", i);
}
printf("[new thread]: exit now.
");
return ((void *)0);
}
int
main(void)
{
int err;
pthread_t tid;
void *tret;
err = pthread_create(&tid, NULL, my_thread, NULL);
if ( err != 0) {
printf("can't create thread: %s
", strerror(err));
exit(-1);
}
sleep(2);
printf("[main thread]: cancel new thread.
");
err = pthread_cancel(tid);
if (err != 0) {
printf("can't cancel thread: %s
", strerror(err));
exit(-1);
}
err = pthread_join(tid, &tret);
if (err != 0) {
printf("can't join with new thread: %s
", strerror(err));
exit(-1);
} else {
if (PTHREAD_CANCELED == tret) {
printf("new thread has been canceled.
");
} else {
printf("new thread exit code: %d
", (int)tret);
}
}
exit(0);
}
プログラムをコンパイルし、ファイルpthread_を生成して実行します.cancel_demo, lienhua34:demo$ gcc -o pthread_cancel_demo -pthread pthread_cancel_demo.c
lienhua34:demo$ ./pthread_cancel_demo
[new thread]: I will sleep 5 seconds.
[new thread]: 1
[main thread]: cancel new thread.
new thread has been canceled.
スレッドがキャンセル要求に応答した場合、PTHREAD_というパラメータが呼び出されたことに相当します.CANCELEEDのpthread_exit関数.
2スレッドキャンセル属性
前に勉強したらpthread_を通じてattr_t構造はスレッドの属性を制御する.しかし、スレッドとキャンセルされた2つのプロパティはpthread_に含まれていません.attr_t構造では、これらはキャンセル可能な状態とキャンセル可能なタイプである.
2.1キャンセル可能ステータス
キャンセル可能ステータス属性は、スレッドが他のスレッドのキャンセル要求に応答するかどうかを制御するイネーブル属性です.この属性はPTHREAD_とすることができるCANCEL_ENABLE、またはPTHREAD_CANCEL_DISABLE.スレッドのキャンセル可能なプロパティのデフォルトは前者です.後者に設定すると、スレッドはキャンセル要求に応答しませんが、キャンセル要求はスレッドにとって未決であり、キャンセル可能状態が再びPTHREAD_になるとCANCEL_ENABLEの場合、スレッドは次のキャンセルポイントですべての未解決のキャンセル要求を処理します.
スレッドはpthread_を呼び出すことができますsetcancelstate関数を使用して、キャンセル可能なステータスを変更します.
#include
int pthread_setcancelstate(int state, int *oldstate);
戻り値:成功した場合は0を返します.そうでない場合はエラー番号を返します.
この関数は、スレッドの現在のキャンセル可能な状態をstateに設定し、oldstateを介して元のキャンセル可能な状態を返します.
次にその例を見てみましょうpthread_cancel_demo.cプログラムの新しいスレッドエントリ関数my_threadの開始呼び出しpthread_setcancelstate関数新しいスレッドのキャンセル可能な状態をPTHREAD_に設定CANCEL_DISABLE. #include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
void *
my_thread(void *arg)
{
int i=0;
int err;
err = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
if (err != 0) {
printf("[new thread]: can't set cancel state: %s
", strerror(err));
}
printf("[new thread: disable cancel state.
");
printf("[new thread]: I will sleep 5 seconds.
");
while (i < 5) {
sleep(1);
i = i + 1;
printf("[new thread]: %d
", i);
}
printf("[new thread]: exit now.
");
return ((void *)0);
}
int
main(void)
{
int err;
pthread_t tid;
void *tret;
err = pthread_create(&tid, NULL, my_thread, NULL);
if ( err != 0) {
printf("can't create thread: %s
", strerror(err));
exit(-1);
}
sleep(2);
printf("[main thread]: cancel new thread.
");
err = pthread_cancel(tid);
if (err != 0) {
printf("can't cancel thread: %s
", strerror(err));
exit(-1);
}
err = pthread_join(tid, &tret);
if (err != 0) {
printf("can't join with new thread: %s
", strerror(err));
exit(-1);
} else {
if (PTHREAD_CANCELED == tret) {
printf("new thread has been canceled.
");
} else {
printf("new thread exit code: %d
", (int)tret);
}
}
exit(0);
}
プログラムをコンパイルし、pthread_を生成して実行します.cancel_demoファイル、lienhua34:demo$ gcc -o pthread_cancel_demo -pthread pthread_cancel_demo.c
lienhua34:demo$ ./pthread_cancel_demo
[new thread: disable cancel state.
[new thread]: I will sleep 5 seconds.
[new thread]: 1
[main thread]: cancel new thread.
[new thread]: 2
[new thread]: 3
[new thread]: 4
[new thread]: 5
[new thread]: exit now.
new thread exit code: 0
上記の実行結果と前節の実行結果を比較すると、新しいスレッドのキャンセル可能な状態をPTHREAD_に設定していることがわかります.CANCEL_DISABLE後、新しいスレッドはメインスレッドのキャンセル要求に応答しませんでした.
2.2キャンセル可能なタイプ
上記のスレッドは、キャンセルポイントに達したときにキャンセルされたかどうかをチェックします.このキャンセルタイプは、遅延キャンセルとも呼ばれます.また、非同期キャンセルのキャンセルタイプもあります.スレッドのキャンセルタイプが非同期キャンセルの場合、スレッドは任意の時間にキャンセルできます.
スレッドはpthread_を呼び出すことができますsetcanceltypeを使用して、スレッドのキャンセルタイプを変更します.
#include
int pthread_setcanceltype(int type, int *oldtype);
戻り値:成功した場合は0を返します.そうでない場合はエラー番号を返します.
ここでtypeパラメータはPTHREAD_であってもよいCANCEL_DEFERRED(遅延キャンセル)、またはPTHREAD_CANCEL_ASYNCAHRONOUS(非同期キャンセル).この関数は、スレッドの現在のキャンセル可能なタイプをtypeに設定し、元のキャンセル可能なタイプをoldtypeパラメータで返します.
(done)
int pthread_cancel(pthread_t tid);
戻り値:成功した場合は0を返します.そうでない場合はエラー符号化を返します.
pthread_cancel呼び出しは、ターゲットスレッドをすぐに終了するのではなく、ターゲットスレッドにキャンセル要求を発行するだけです.呼び出しスレッドは、ターゲットスレッドの終了を待たずに実行されます.デフォルトでは、ターゲットスレッドは、ターゲットスレッドがキャンセルポイントに到達するまで、キャンセル要求が発行された後も実行されます.キャンセルポイントは、スレッドがキャンセルされたかどうかをチェックし、要求に従って動作する場所です.
スレッドキャンセルの例を見てみましょう.メインスレッドは新しいスレッドを作成し、新しいスレッドは5秒間睡眠を取ってから2を返します.プライマリスレッドは、新しいスレッドを作成してから2秒寝てpthreadを呼び出します.cancelは、新しいスレッドのキャンセルを要求します.最後に、新しいスレッドの終了ステータスを取得します.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
void *
my_thread(void *arg)
{
int i=0;
printf("[new thread]: I will sleep 5 seconds.
");
while (i < 5) {
sleep(1);
i = i + 1;
printf("[new thread]: %d
", i);
}
printf("[new thread]: exit now.
");
return ((void *)0);
}
int
main(void)
{
int err;
pthread_t tid;
void *tret;
err = pthread_create(&tid, NULL, my_thread, NULL);
if ( err != 0) {
printf("can't create thread: %s
", strerror(err));
exit(-1);
}
sleep(2);
printf("[main thread]: cancel new thread.
");
err = pthread_cancel(tid);
if (err != 0) {
printf("can't cancel thread: %s
", strerror(err));
exit(-1);
}
err = pthread_join(tid, &tret);
if (err != 0) {
printf("can't join with new thread: %s
", strerror(err));
exit(-1);
} else {
if (PTHREAD_CANCELED == tret) {
printf("new thread has been canceled.
");
} else {
printf("new thread exit code: %d
", (int)tret);
}
}
exit(0);
}
プログラムをコンパイルし、ファイルpthread_を生成して実行します.cancel_demo,
lienhua34:demo$ gcc -o pthread_cancel_demo -pthread pthread_cancel_demo.c
lienhua34:demo$ ./pthread_cancel_demo
[new thread]: I will sleep 5 seconds.
[new thread]: 1
[main thread]: cancel new thread.
new thread has been canceled.
スレッドがキャンセル要求に応答した場合、PTHREAD_というパラメータが呼び出されたことに相当します.CANCELEEDのpthread_exit関数.
2スレッドキャンセル属性
前に勉強したらpthread_を通じてattr_t構造はスレッドの属性を制御する.しかし、スレッドとキャンセルされた2つのプロパティはpthread_に含まれていません.attr_t構造では、これらはキャンセル可能な状態とキャンセル可能なタイプである.
2.1キャンセル可能ステータス
キャンセル可能ステータス属性は、スレッドが他のスレッドのキャンセル要求に応答するかどうかを制御するイネーブル属性です.この属性はPTHREAD_とすることができるCANCEL_ENABLE、またはPTHREAD_CANCEL_DISABLE.スレッドのキャンセル可能なプロパティのデフォルトは前者です.後者に設定すると、スレッドはキャンセル要求に応答しませんが、キャンセル要求はスレッドにとって未決であり、キャンセル可能状態が再びPTHREAD_になるとCANCEL_ENABLEの場合、スレッドは次のキャンセルポイントですべての未解決のキャンセル要求を処理します.
スレッドはpthread_を呼び出すことができますsetcancelstate関数を使用して、キャンセル可能なステータスを変更します.
#include
int pthread_setcancelstate(int state, int *oldstate);
戻り値:成功した場合は0を返します.そうでない場合はエラー番号を返します.
この関数は、スレッドの現在のキャンセル可能な状態をstateに設定し、oldstateを介して元のキャンセル可能な状態を返します.
次にその例を見てみましょうpthread_cancel_demo.cプログラムの新しいスレッドエントリ関数my_threadの開始呼び出しpthread_setcancelstate関数新しいスレッドのキャンセル可能な状態をPTHREAD_に設定CANCEL_DISABLE. #include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
void *
my_thread(void *arg)
{
int i=0;
int err;
err = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
if (err != 0) {
printf("[new thread]: can't set cancel state: %s
", strerror(err));
}
printf("[new thread: disable cancel state.
");
printf("[new thread]: I will sleep 5 seconds.
");
while (i < 5) {
sleep(1);
i = i + 1;
printf("[new thread]: %d
", i);
}
printf("[new thread]: exit now.
");
return ((void *)0);
}
int
main(void)
{
int err;
pthread_t tid;
void *tret;
err = pthread_create(&tid, NULL, my_thread, NULL);
if ( err != 0) {
printf("can't create thread: %s
", strerror(err));
exit(-1);
}
sleep(2);
printf("[main thread]: cancel new thread.
");
err = pthread_cancel(tid);
if (err != 0) {
printf("can't cancel thread: %s
", strerror(err));
exit(-1);
}
err = pthread_join(tid, &tret);
if (err != 0) {
printf("can't join with new thread: %s
", strerror(err));
exit(-1);
} else {
if (PTHREAD_CANCELED == tret) {
printf("new thread has been canceled.
");
} else {
printf("new thread exit code: %d
", (int)tret);
}
}
exit(0);
}
プログラムをコンパイルし、pthread_を生成して実行します.cancel_demoファイル、lienhua34:demo$ gcc -o pthread_cancel_demo -pthread pthread_cancel_demo.c
lienhua34:demo$ ./pthread_cancel_demo
[new thread: disable cancel state.
[new thread]: I will sleep 5 seconds.
[new thread]: 1
[main thread]: cancel new thread.
[new thread]: 2
[new thread]: 3
[new thread]: 4
[new thread]: 5
[new thread]: exit now.
new thread exit code: 0
上記の実行結果と前節の実行結果を比較すると、新しいスレッドのキャンセル可能な状態をPTHREAD_に設定していることがわかります.CANCEL_DISABLE後、新しいスレッドはメインスレッドのキャンセル要求に応答しませんでした.
2.2キャンセル可能なタイプ
上記のスレッドは、キャンセルポイントに達したときにキャンセルされたかどうかをチェックします.このキャンセルタイプは、遅延キャンセルとも呼ばれます.また、非同期キャンセルのキャンセルタイプもあります.スレッドのキャンセルタイプが非同期キャンセルの場合、スレッドは任意の時間にキャンセルできます.
スレッドはpthread_を呼び出すことができますsetcanceltypeを使用して、スレッドのキャンセルタイプを変更します.
#include
int pthread_setcanceltype(int type, int *oldtype);
戻り値:成功した場合は0を返します.そうでない場合はエラー番号を返します.
ここでtypeパラメータはPTHREAD_であってもよいCANCEL_DEFERRED(遅延キャンセル)、またはPTHREAD_CANCEL_ASYNCAHRONOUS(非同期キャンセル).この関数は、スレッドの現在のキャンセル可能なタイプをtypeに設定し、元のキャンセル可能なタイプをoldtypeパラメータで返します.
(done)
int pthread_setcancelstate(int state, int *oldstate);
戻り値:成功した場合は0を返します.そうでない場合はエラー番号を返します.
この関数は、スレッドの現在のキャンセル可能な状態をstateに設定し、oldstateを介して元のキャンセル可能な状態を返します.
次にその例を見てみましょうpthread_cancel_demo.cプログラムの新しいスレッドエントリ関数my_threadの開始呼び出しpthread_setcancelstate関数新しいスレッドのキャンセル可能な状態をPTHREAD_に設定CANCEL_DISABLE.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
void *
my_thread(void *arg)
{
int i=0;
int err;
err = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
if (err != 0) {
printf("[new thread]: can't set cancel state: %s
", strerror(err));
}
printf("[new thread: disable cancel state.
");
printf("[new thread]: I will sleep 5 seconds.
");
while (i < 5) {
sleep(1);
i = i + 1;
printf("[new thread]: %d
", i);
}
printf("[new thread]: exit now.
");
return ((void *)0);
}
int
main(void)
{
int err;
pthread_t tid;
void *tret;
err = pthread_create(&tid, NULL, my_thread, NULL);
if ( err != 0) {
printf("can't create thread: %s
", strerror(err));
exit(-1);
}
sleep(2);
printf("[main thread]: cancel new thread.
");
err = pthread_cancel(tid);
if (err != 0) {
printf("can't cancel thread: %s
", strerror(err));
exit(-1);
}
err = pthread_join(tid, &tret);
if (err != 0) {
printf("can't join with new thread: %s
", strerror(err));
exit(-1);
} else {
if (PTHREAD_CANCELED == tret) {
printf("new thread has been canceled.
");
} else {
printf("new thread exit code: %d
", (int)tret);
}
}
exit(0);
}
プログラムをコンパイルし、pthread_を生成して実行します.cancel_demoファイル、
lienhua34:demo$ gcc -o pthread_cancel_demo -pthread pthread_cancel_demo.c
lienhua34:demo$ ./pthread_cancel_demo
[new thread: disable cancel state.
[new thread]: I will sleep 5 seconds.
[new thread]: 1
[main thread]: cancel new thread.
[new thread]: 2
[new thread]: 3
[new thread]: 4
[new thread]: 5
[new thread]: exit now.
new thread exit code: 0
上記の実行結果と前節の実行結果を比較すると、新しいスレッドのキャンセル可能な状態をPTHREAD_に設定していることがわかります.CANCEL_DISABLE後、新しいスレッドはメインスレッドのキャンセル要求に応答しませんでした.
2.2キャンセル可能なタイプ
上記のスレッドは、キャンセルポイントに達したときにキャンセルされたかどうかをチェックします.このキャンセルタイプは、遅延キャンセルとも呼ばれます.また、非同期キャンセルのキャンセルタイプもあります.スレッドのキャンセルタイプが非同期キャンセルの場合、スレッドは任意の時間にキャンセルできます.
スレッドはpthread_を呼び出すことができますsetcanceltypeを使用して、スレッドのキャンセルタイプを変更します.
#include
int pthread_setcanceltype(int type, int *oldtype);
戻り値:成功した場合は0を返します.そうでない場合はエラー番号を返します.
ここでtypeパラメータはPTHREAD_であってもよいCANCEL_DEFERRED(遅延キャンセル)、またはPTHREAD_CANCEL_ASYNCAHRONOUS(非同期キャンセル).この関数は、スレッドの現在のキャンセル可能なタイプをtypeに設定し、元のキャンセル可能なタイプをoldtypeパラメータで返します.
(done)