POSIX线程的创建和取消
POSIX线程的创建和取消
先看一个例子:pthread1.c
- #if defined(WIN32)
- #include <windows.h> // void Sleep(DWORD ms)
- #define SLEEP(ms) Sleep(ms)
- #else if defined(LINUX)
- #include <unistd.h> // unsigned int sleep(unsigned int)
- #include <stdio.h>
- #include <stdlib.h>
- #define SLEEP(ms) sleep(ms)
- #endif
- #include <pthread.h>
- /** 作为线程入口的函数 */
- void * print_message_function(void *ptr)
- {
- SLEEP(5);
- char *message;
- message = (char *) ptr;
- printf("%s \n", message);
- return NULL;
- }
- int main(int argc, char* argv[])
- {
- pthread_t thread1, thread2;
- char *message1 = "Thread 1";
- char *message2 = "Thread 2";
- int iret1, iret2;
- // 成功创建线程时返回零
- iret1 = pthread_create(&thread1, NULL, &print_message_function, (void*) message1);
- iret2 = pthread_create(&thread2, NULL, &print_message_function, (void*) message2);
- /* 等待两个线程结束 -- 同步
- * 如果不同步,则有可能主线程的return先执行,导致子线程未完成任务而先完蛋
- * 可以启用Sleep试试。
- */
- pthread_join(thread1, NULL);
- pthread_join(thread2, NULL);
- printf("Thread 1 returns: %d\n", iret1);
- printf("Thread 2 returns: %d\n", iret2);
- return 0;
- }
- 在Linux下编译:
* C++ compiler: g++ -lpthread pthread1.c
- 结束线程的方法:
* 让函数自己返回
* exit 停止整个进程(当然包括所有的线程)
- 创建线程的函数原型:
- int pthread_create(pthread_t * thread,
- const pthread_attr_t * attr,
- void* (*start_routine)(void*),
- void *arg);
- pthread_create 的第二个参数pthread_attr_t
struct pthread_attr_t
{
enum 新线程是否与进程中其它线程脱离同步
{
PTHREAD_CREATE_JOINABLE [default] 可以在创建后用 pthread_detach 脱离同步
PTHREAD_CREATE_DETACHED 不能用 pthread_join 来同步,退出时自行释放资源
} __detachstate;
enum 新线程的调用策略
{
SCHED_OTHER [default] 非实时
SCHED_RR 实时,轮转法 - 仅对超级用户有效
SCHED_FIFO 实时,先入先出 - 仅对超级用户有效
} __schedpolicy;
struct sched_param 在运行时用 pthread_setschedparam 更新。
{
int sched_priority 线程的运行优先级。当上面的 __schedpolicy 为“实时”时才有效。缺省是零。
} __schedparam;
enum
{
PTHREAD_EXPLICIT_SCHED [default] 显式指定调度策略和调度参数,即使用 attr 中的值
PTHREAD_INHERIT_SCHED 继承调用者线程的值
} __inheritsched;
enum 线程间竞争CPU的范围
{
PTHREAD_SCOPE_SYSTEM [default] 目前Linux只实现了这一种
PTHREAD_SCOPE_PROCESS 仅与同进程的线程竞争
} __scope;
}
下面三个没用过
* guard size
* stack address (See unistd.h and bits/posix_opt.h _POSIX_THREAD_ATTR_STACKADDR)
* stack size (default minimum PTHREAD_STACK_SIZE set in pthread.h)
- 创建线程时,如果写成下面的样子,也是可以的。这属于精简模式,作为函数指针的传入参数是和上面等价的:
- 等待其它线程停止
* th - 调用线程变为挂起状态,等待线程退出。退出线程可用 pthread_exit() 或者 cancel 类线程函数。
* thread_return - 不置为NULL的话,可以传出返回值。
- 退出当前线程
若要在退出时返回数据在retval指向的内存里,务必保证该内存不是在线程局部空间里,否则会随着线程退出而消失。
- 可以通过向某线程发送cancel请求而强制终止该线程。
POSIX标准规定的取消点:
- pthread_join()、pthread_testcancel()、pthread_cond_wait()、pthread_cond_timedwait()、sem_wait()、sigwait()
- read、write等会引起阻塞的系统调用
但pthread_cancel的手册页声称,由于LinuxThread库与C库结合得不好,因而目前C库函数都不是取消点。
不过,cancel信号会使线程从阻塞的系统调用中退出,并置EINTR错误码。所以可以把这样的系统调用作为取消点:
pthread_testcancel();
retcode = read(fd, buffer, length);
pthread_testcancel();
这样,可达到POSIX的要求。
- 与取消线程相关的函数
- int pthread_cancel (pthread_t th) 发送取消信号给线程。若成功返回零;失败则非零。发送成功并不意味着线程会终止。
- int pthread_setcancelstate (int state, int *oldstate) 设置本线程对cancel信号的反应。
enum
{
PTHREAD_CANCEL_ENABLE [default] 收到信号后置自己为取消状态
PTHREAD_CANCEL_DISABLE 忽略cancel信号,继续运行
} state
- int pthread_setcanceltype (int type int *oldtype)
enum
{
PTHREAD_CANCEL_DEFERRED [default] 收到cancel信号后继续运行,到达取消点时退出
PTHREAD_CANCEL_ASYNCHRONOUS 立即退出
} type 当上面的state为 PTHREAD_CANCEL_ENABLE 时该变量才有效。
- void pthread_testcancel (void)
检查本线程是否处于取消状态,若是,立刻退出。
- #ifdef WIN32
- #include <windows.h>
- #define SLEEP(ms) Sleep(ms)
- #else if defined(LINUX)
- #include <stdio.h>
- #define SLEEP(ms) sleep(ms)
- #endif
- #include <cassert>
- #include <pthread.h>
- static int s_nThreadResult = 0;
- void * theThread(void * param)
- {
- int count = 0;
- while (count < 20)
- {
- printf("[Child] looping\n");
- pthread_testcancel();
- SLEEP(1);
- count ++;
- }
- s_nThreadResult = 1;
- pthread_exit(&s_nThreadResult);
- return NULL;
- }
- int main(int argc, char * argv[])
- {
- int rc = 0;
- pthread_t tid;
- rc = pthread_create(&tid, NULL, &theThread, NULL);
- assert(rc == 0 && "pthread_create");
- SLEEP(3);
- // 若启用下面代码,则子线程提前返回
- //rc = pthread_cancel(tid);
- assert(rc == 0 && "pthread_cancel");
- // 阻塞自己,等待子线程返回
- void * status = NULL;
- rc = pthread_join(tid, &status);
- assert(rc == 0 && "pthread_join", rc);
- // 若子线程是被取消从而结束的,则无返回值
- if (status != PTHREAD_CANCELED && status != NULL)
- {
- printf("Returned value from thread: %d\n", *(int *)status);
- }
- return 0;
- }
评论暂时关闭