精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
取消线程通常不是由该程序自身发起的,而是由其它的线程发起。
取消线程的时候要注意,如果我们应用程序中,对于清除数据与解锁的处理机制不合理时,将可能会破坏数据,或造成应用程序死锁。
在下面这个例子中,子线程所调用的函数每隔一秒钟打印一行,主程序在创建子线程3秒钟后,发出取消该子线程的指令。
主要使用的函数为 pthread_cancel(),API 函数说明见pthread_cancel 取消线程
注意到使用了 pthread_cancel 之后,仍然要使用pthread_join 函数等待子线程结束;
如 果子线程被成功取消, 那么pthread_join 函数取到的状态将为PTHREAD_CANCELED。
#define _MULTI_THREADED
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define checkResults(string, val) { \
if (val) { \
printf("Failed with %d at %s", val, string); \
exit(1); \
} \
}
void *theThread(void *parm)
{
printf("Thread: Entered\n");
while (1) {
printf("Thread: Looping or long running request\n");
pthread_testcancel();
sleep(1);
}
return NULL;
}
int main(int argc, char **argv)
{
pthread_t thread;
int rc=0;
void *status;
printf("Enter Testcase - %s\n", argv[0]);
printf("Create/start a thread\n");
rc = pthread_create(&thread, NULL, theThread, NULL);
checkResults("pthread_create()\n", rc);
printf("Wait a bit until we 'realize' the thread needs to be canceled\n");
sleep(3);
rc = pthread_cancel(thread);
checkResults("pthread_cancel()\n", rc);
printf("Wait for the thread to complete, and release its resources\n");
rc = pthread_join(thread, &status);
checkResults("pthread_join()\n", rc);
printf("Thread status indicates it was canceled\n");
if (status != PTHREAD_CANCELED) {
printf("Unexpected thread status\n");
}
printf("Main completed\n");
return 0;
}
有时我们需要暂时停止线程的运行。当我们挂起一个线程时,这个线程的状态,以及线程属性、锁住的记录, 都将维持现状,直至线程重新开始运行(resume)。
挂起线程时要小心,因为这可能会导致应用程序死锁,或超时。我们可以使用其它更安全的方式来解决大部分问题,包括挂起线程。(比如说同步机制)
挂起线程后,我们需要在应用程序中重新启用这个线程,重新启用后,线程将从挂起点继续开始运行。
当我们使用线程的时候,知道线程何时结束是很重要的。等待线程执行一个操作,或等待线程发生一个事件,称之为同步机制。
常见的等待,就是等待至线程结束。当线程结束的时候,应用程序将会被提示线程分配的工作已完成,或线程运行失败。我们可以通过API 函数中设置的参数来确认线程运行的成功与否。
在大型的应用程序中,等待一组线程结束可能是一种比较好的方式。比如说通过调用程序
在下面这个例子中,主程序启动了多个子线程,并等待这些子线程结束,然后检查子线程的结束状态。
在这个例子中,等待一个线程结束使用到的函数仍然是 pthread_join.
#define _MULTI_THREADED
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define THREADGROUPSIZE 5
#define checkResults(string, val) { \
if (val) { \
printf("Failed with %d at %s", val, string); \
exit(1); \
} \
}
void *theThread(void *parm)
{
printf("Thread %.8x %.8x: Entered\n", pthread_getthreadid_np());
printf("Thread %.8x %.8x: Working\n", pthread_getthreadid_np());
sleep(15);
printf("Thread %.8x %.8x: Done with work\n", pthread_getthreadid_np());
return NULL;
}
int main(int argc, char **argv)
{
pthread_t thread[THREADGROUPSIZE];
void *status[THREADGROUPSIZE];
int i;
int rc=0;
printf("Enter Testcase - %s\n", argv[0]);
printf("Create/start some worker threads\n");
for (i=0; i <THREADGROUPSIZE; ++i)
{
rc = pthread_create(&thread[i], NULL, theThread, NULL);
checkResults("pthread_create()\n", rc);
}
printf("Wait for worker threads to complete, release their resources\n");
for (i=0; i <THREADGROUPSIZE; ++i) {
rc = pthread_join(thread[i], &status[i]);
checkResults("pthread_join()\n", rc);
}
printf("Check all thread's results\n");
for (i=0; i <THREADGROUPSIZE; ++i) {
if (status[i] != NULL) {
printf("Unexpected thread status\n");
}
}
有时,我们的应用程序需要使当前的线程让步于进程中其它线程。
当线程发出一个让步指令 yielding 时,系统将会立刻运行另一个相等或更高优先级的,活动中的线程。如果当时准备运行的线程中,没有优先极相等可更高的,那么让步指令将不会产生效果。让步机制是实时处理的,不会对之后的任务产生附加的影响。相关的API 函数为sched_yield.
目前400 的i 平台上,提供了全面的多任务计划的算法。在一个写法良好的应用程序中,线程很少需要采用让步,因为系统提供了很多用来同步线程的API。