电竞比分网-中国电竞赛事及体育赛事平台

分享

線程取消

 mediatv 2014-04-03

 

取消線程

         取消操作允許線程請求終止其所在進程中的任何其他線程。不希望或不需要對一組相關(guān)的線程執(zhí)行進一步操作時,可以選擇執(zhí)行取消操作。例如,用戶請求關(guān)閉或退出正在運行的應(yīng)用程序。另一個示例是完成由許多線程執(zhí)行的任務(wù)。其中的某個線程可能最終完成了該任務(wù),而其它線程還在繼續(xù)運行。由于正在運行的線程此時沒有任何用處,因此取消這個線程。

取消點

         僅當取消操作安全時才應(yīng)取消線程。pthreads標準指定了幾個取消點,其中包括:

  •                   通過pthread_testcancel調(diào)用以編程方式建立線程取消點。
  •                   線程等待pthread_cond_waitpthread_cond_timewait()中的特定條件。
  •                   被sigwait(2)阻塞的函數(shù)
  •                   一些標準的庫調(diào)用。通常,這些調(diào)用包括線程可基于阻塞的函數(shù)。

     缺省情況下,將啟用取消功能。有時,您可能希望應(yīng)用程序禁用取消功能。如果禁用取消功能,則會導(dǎo)致延遲所有的取消請求,直到再次啟用取消請求。  根據(jù)POSIX標準,pthread_join()、pthread_testcancel()、pthread_cond_wait()、pthread_cond_timedwait()、sem_wait()、sigwait()等函數(shù)以及read()、write()等會引起阻塞的系統(tǒng)調(diào)用都是Cancelation-point,而其他pthread函數(shù)都不會引起Cancelation動作。但是pthread_cancel的手冊頁聲稱,由于LinuxThread庫與C庫結(jié)合得不好,因而目前C庫函數(shù)都不是Cancelation-point;但CANCEL信號會使線程從阻塞的系統(tǒng)調(diào)用中退出,并置EINTR錯誤碼,因此可以在需要作為Cancelation-point的系統(tǒng)調(diào)用前后調(diào)用pthread_testcancel(),從而達到POSIX標準所要求的目標,即如下代碼段:
pthread_testcancel();
retcode = read(fd, buffer, length);
pthread_testcancel();

注意:

程序設(shè)計方面的考慮
如果線程處于無限循環(huán)中,且循環(huán)體內(nèi)沒有執(zhí)行至取消點的必然路徑,則線程無法由外部其他線程的取消請求而終止。因此在這樣的循環(huán)體的必經(jīng)路徑上應(yīng)該加入pthread_testcancel()調(diào)用。

放置取消點

         執(zhí)行取消操作存在一定的危險。大多數(shù)危險都與完全恢復(fù)不變量和釋放共享資源有關(guān)。取消線程時一定要格外小心,否則可能會使互斥保留為鎖定狀態(tài),從而導(dǎo)致死鎖狀態(tài)?;蛘撸讶∠木€程可能保留已分配的內(nèi)存區(qū)域,但是系統(tǒng)無法識別這一部分內(nèi)存,從而無法釋放它。

         標準C庫指定了一個取消接口用于以編程方式允許或禁止取消功能。該庫定義的取消點是一組可能會執(zhí)行取消操作的點。該庫還允許定義取消處理程序的范圍,以確保這些處理程序在預(yù)期的時間和位置運行。取消處理程序提供的清理服務(wù)可以將資源和狀態(tài)恢復(fù)到與起點一致的狀態(tài)。

         必須對應(yīng)用程序有一定的了解,才能放置取消點并執(zhí)行取消處理程序?;コ饪隙ú皇?/span>取消點,只應(yīng)當在必要時使之保留盡可能短的時間。請將異步取消區(qū)域限制在沒有外部依賴性的序列,因為外部依賴性可能會產(chǎn)生掛起的資源或未解決的狀態(tài)條件。在從某個備用的嵌套取消狀態(tài)返回時,一定要小心地恢復(fù)取消狀態(tài)。該接口提供便于進行恢復(fù)的功能:pthread_setcancelstate(3C) 在所引用的變量中保留當前的取消狀態(tài),pthread_setcanceltype(3C) 以同樣的方式保留當前的取消類型。

         在以下三種情況下可能會執(zhí)行取消操作:

  •                異步
  •                執(zhí)行序列中按照標準定義的點
  •                調(diào)用pthread_cancel()

取消線程方面的函數(shù)

int pthread_cancel(pthread_t thread);

返回:

成功之后返回0。失敗返回錯誤號,錯誤號說明如下:

ESRCH:沒有找到線程ID相對應(yīng)的線程。

int pthread_setcancelstate(int state, int *oldstate);設(shè)置本線程對信號的反應(yīng)

狀態(tài)有兩種:

   PTHREAD_CANCEL_ENABLE 默認,收到cancel信號馬上設(shè)置退出狀態(tài)。

   PTHREAD_CANCEL_DISABLE 收到cancel信號繼續(xù)運行。

返回:

         成功之后返回0。失敗返回錯誤號,錯誤號說明如下:

         EINVAL:狀態(tài)不是PTHREAD_CANCEL_ENABLE或者PTHREAD_CANCEL_DISABLE

int pthread_setcanceltype(int type, int *oldtype);

類型有兩種,只有在PTHREAD_CANCEL_ENABLE狀態(tài)下有效

PTHREAD_CANCEL_ASYNCHRONOUS 立即執(zhí)行取消信號

   PTHREAD_CANCEL_DEFERRED                   運行到下一個取消點

返回:

         成功之后返回0.失敗返回錯誤號,錯誤號說明如下:

         EINVAL:狀態(tài)不是PTHREAD_CANCEL_ASYNCHRONOUS或者PTHREAD_CANCEL_DEFERRED       

void pthread_testcancel(void);

當線程取消功能處于啟用狀態(tài)且取消狀態(tài)設(shè)置為延遲狀態(tài)時,pthread_testcancel()函數(shù)有效。如果在取消功能處處于禁用狀態(tài)下調(diào)用pthread_testcancel(),則該函數(shù)不起作用。

請務(wù)必僅在線程取消線程操作安全的序列中插入pthread_testcancel()。除通過pthread_testcancel()調(diào)用以編程方式建立的取消點意外,pthread標準還指定了幾個取消點。

測試退出點,就是測試cancel信號

 

線程取消點例子

線程中沒有取消點

 

 1#include <pthread.h>
 2
 3#include <stdio.h>
 4
 5#include <unistd.h>
 6
 7 
 8
 9void* thr(void* arg)
10
11{
12
13         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
14
15         pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
16
17         
18
19         while(1)
20
21         {
22
23                   ;
24
25         }

26
27         printf("thread is not running\n");
28
29         sleep(2);
30
31}

32
33 
34
35int main()
36
37{
38
39         pthread_t th1;
40
41         int err;
42
43         err = pthread_create(&th1,NULL,thr,NULL);
44
45         pthread_cancel(th1);
46
47         pthread_join(th1,NULL);
48
49         printf("Main thread is exit\n");
50
51         return 0;
52
53}

54

 

子線程中有取消點

 1#include <pthread.h>
 2
 3#include <stdio.h>
 4
 5#include <unistd.h>
 6
 7 
 8
 9void* thr(void* arg)
10
11{
12
13         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
14
15         pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
16
17         
18
19         while(1)
20
21         {
22
23                   printf("thread is running\n");
24
25         }

26
27         printf("thread is not running\n");
28
29         sleep(2);
30
31}

32
33 
34
35int main()
36
37{
38
39         pthread_t th1;
40
41         int err;
42
43         err = pthread_create(&th1,NULL,thr,NULL);
44
45         pthread_cancel(th1);
46
47         pthread_join(th1,NULL);
48
49         printf("Main thread is exit\n");
50
51         return 0;
52
53}

54
55


異步取消(HP沒有成功)

 1#include <pthread.h>
 2
 3#include <stdio.h>
 4
 5#include <unistd.h>
 6
 7 
 8
 9void* thr(void* arg)
10
11{
12
13         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
14
15         pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
16
17         
18
19         while(1)
20
21         {
22
23                   ;
24
25         }

26
27         printf("thread is not running\n");
28
29         sleep(2);
30
31}

32
33 
34
35int main()
36
37{
38
39         pthread_t th1;
40
41         int err;
42
43         err = pthread_create(&th1,NULL,thr,NULL);
44
45         pthread_cancel(th1);
46
47         pthread_join(th1,NULL);
48
49         sleep(1);
50
51         printf("Main thread is exit\n");
52
53         return 0;
54
55}

56
57


設(shè)置不可取消

 1#include <pthread.h>
 2
 3#include <stdio.h>
 4
 5#include <unistd.h>
 6
 7 
 8
 9void* thr(void* arg)
10
11{
12
13         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
14
15         pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
16
17         
18
19         while(1)
20
21         {
22
23                   printf("thread is running\n");
24
25         }

26
27         printf("thread is not running\n");
28
29         sleep(2);
30
31}

32
33 
34
35int main()
36
37{
38
39         pthread_t th1;
40
41         int err;
42
43         err = pthread_create(&th1,NULL,thr,NULL);
44
45         pthread_cancel(th1);
46
47         pthread_join(th1,NULL);
48
49         sleep(1);
50
51         printf("Main thread is exit\n");
52
53         return 0;
54
55}

56
57


設(shè)置取消點

 

 1#include <pthread.h>
 2
 3#include <stdio.h>
 4
 5#include <unistd.h>
 6
 7 
 8
 9void* thr(void* arg)
10
11{
12
13         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
14
15         pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
16
17         
18
19         while(1)
20
21         {
22
23                   ;
24
25                   pthread_testcancel();
26
27         }

28
29         printf("thread is not running\n");
30
31         sleep(2);
32
33}

34
35 
36
37int main()
38
39{
40
41         pthread_t th1;
42
43         int err;
44
45         err = pthread_create(&th1,NULL,thr,NULL);
46
47         pthread_cancel(th1);
48
49         pthread_join(th1,NULL);
50
51         sleep(1);
52
53         printf("Main thread is exit\n");
54
55         return 0;
56
57}

58

 


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多