UNIX线程

UNIX线程

转自:http://blog.csdn.net/yang_yulei/article/details/17595901

单个控制线程的进程在同一时刻只做一件事情,有了多个控制线程以后,在程序设计时可以把进程设计成在同一时刻能够做不止一件事,每个线程处理各自独立的任务。

 

使用多线程的好处:

1、  通过为每种事件类型的处理分配单独的线程,能够简化处理异步事件的代码。

2、  多个进程必须使用操作系统提供的复杂机制才能实现内存和文件描述符的共享,而多个线程自动地可以访问相同的存储空间和文件描述符。

3、  有了多线程,相互独立的任务的处理可以交叉进行,只需要为每个任务分配一个单独的线程。改善整个程序的吞吐量。

4、  交互的程序同样可以通过使用多线程实现响应时间的改善。

 

不管处理器的个数是多少,程序可以通过使用线程得以简化。而且,即使多线程程序在串行化任务时不得不阻塞,由于某些线程在阻塞的时候还有另外一些线程可以运行,所以多线程程序在单处理器上运行仍然能够改善响应时间和吞吐量

 

【进程的所有信息对该进程的所有线程都是共享的,包括可执行的程序文本、程序的全局内存和堆内存、栈以及文件描述符。】

 

线程标识

进程ID在整个系统中是唯一的,但线程ID不同,线程ID只在它所属的进程环境中有效。

 

线程可以通过调用pthread_self函数获得自身的线程ID

(注意:linux默认不连接pthread库,故在编译时要手动链接:gcc test.c -l pthread.h)

#include <pthread.h>

pthread_t  pthread_self (void) ;

线程ID则用pthread_t数据类型来表示,实现的时候可用一个结构来代表pthread_t数据类型,因此必须使用函数来对两个线程ID进行比较。

 

#include <pthread.h>

int  pthread_equal (pthread_t tid1, pthread tid2) ;

若相等则返回非0值,否则返回0.

 

线程创建

在创建多个控制线程以前,程序的行为与传统的进程并没有什么区别。新增的线程可以通过调用pthread_create函数创建。

#include <pthread.h>

int  pthread_create(pthread_t * tidp,                   //线程ID指针

                                  const pthread_attr_t * attr,  //线程属性指针

                                 void *(*start_rtn)(void *),    //线程函数

                                 void * arg                            //线程函数参数结构指针) ;

新创建的线程从start_rtn函数的地址开始运行。该函数只有一个无类型指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。

 

注意:pthread函数在调用失败时通常会返回错误码,它们并不像其他的POSIX函数一样设置errno

线程函数一定要形如:void* func(void* arg) 才可以无警告编译通过

 

线程终止

如果进程中的任一线程调用了exit_Exit_exit,那么整个进程就会终止。

单个线程可以通过下列三种方式退出,在不终止整个进程的情况下停止它的控制流。

1、  线程从启动例程中返回。(函数执行完,自然退出)

2、  线程被同一进程中的其他线程取消。

3、  线程调用pthread_exit

 

#include <pthread.h>

void  pthead_exit(void * rval_ptr) ;

rval_ptr指向线程的返回码,若线程被取消,则返回码为PTHEAD_CANCELED

 

进程中的其他线程可通过调用pthread_join函数访问到这个指针。(即获取进程的终止状态)

#include <pthread.h>

int  pthread_join(pthread_t tid,  void** rval_ptr) ;

调用线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。

 

线程可以通过调用pthread_cancel函数来请求取消同一进程中的其他线程。

#include <pthread.h>

int  pthread_cancel(pthread_t tid) ;

被要求取消的线程可以选择忽略请求,或控制取消方式

 

线程清理处理程序

线程可以建立多个清理处理程序。记录在栈中,即它们的执行顺序与它们注册顺序相反。(进程的清理处理函数也是如此)

#include <pthread.h>

void  pthread_cleanup_push(void(*rtn)(void *),  void *arg) ;

void  pthread_cleanup_pop(int execute) ;

清理函数被执行当:

①   调用pthread_exit时

②   响应取消请求时

③   调用pthread_cleanup_pop(参数execute不为0)

 

注意:pthread_cleanup_pushpthread_cleanup_pop在一个函数中要配对使用,否则会编译出错。若想让线程在退出时自动执行清理函数,则在配对使用时,pthread_cleanup_pop(0);pop的参数置为0,则清理函数不被其调用。

 

注意:若线程是自然终止或是return而终止的,那么它的清理处理函数就不会被调用。(这点与进程的清理处理函数不同)

  1. //线程退出清理函数  
  2. //  
  3.   
  4. #include <pthread.h>  
  5. #include <stdio.h>  
  6. #include <errno.h>  
  7. #include <stdlib.h>   
  8.   
  9. void cleanup(void* arg);  
  10. void* thr_fn1(void* arg);  
  11. void* thr_fn2(void* arg) ;  
  12.    
  13. int   
  14. main(void)  
  15. {  
  16.     pthread_t tid1, tid2;  
  17.     void* tret ;  
  18.    
  19.     if (pthread_create(&tid1, NULL, thr_fn1, (void*)0) != 0)  
  20.         perror("can't create thread1 \n") ;  
  21.     if (pthread_create(&tid2, NULL, thr_fn2, (void*)0) != 0)  
  22.         perror("can't create thread1 \n") ;  
  23.   
  24.     pthread_join(tid1, &tret) ;  
  25.     printf("thread 1 exit code %d\n", (int)tret) ;  
  26.     pthread_join(tid2, &tret) ;  
  27.     printf("thread 2 exit code %d\n", (int)tret) ;  
  28.       
  29.     exit(0) ;  
  30. }   
  31.   
  32. void  
  33. cleanup(void* arg)  
  34. {  
  35.     printf("cleanup: %s\n", (char*)arg) ;  
  36. }  
  37.   
  38. void*  
  39. thr_fn1(void* arg)  
  40. {  
  41.     printf("thread 1 start\n") ;  
  42.     pthread_cleanup_push(cleanup, "thread 1 first handler") ;  
  43.     pthread_cleanup_push(cleanup, "thread 1 second  handler") ;  
  44.       
  45.     printf("thread 1 push complete\n") ;  
  46.   
  47.     pthread_cleanup_pop(0) ;  
  48.     pthread_cleanup_pop(0) ;  
  49.   
  50.     return ((void*)1) ;  
  51. }  
  52.   
  53. void*  
  54. thr_fn2(void* arg)  
  55. {  
  56.     printf("thread 2 start\n") ;  
  57.   
  58.     pthread_cleanup_push(cleanup, "thread 2 first handler") ;  
  59.     pthread_cleanup_push(cleanup, "thread 2 second  handler") ;  
  60.   
  61.     printf("thread 2 push complete\n") ;  
  62.   
  63.     pthread_cleanup_pop(0) ;  
  64.     pthread_cleanup_pop(0) ;  
  65.   
  66.     pthread_exit ((void*)2) ;  
  67. }  

 

 

进程原语

     线程原语

描述

getpid

pthread_self

获取控制流的ID

fork

pthread_create

创建新的控制流

exit

pthread_exit

从现有的控制流中退出

waitpid

pthread_join

从控制流中得到退出状态

atexit

pthread_cleanup_push

注册退出清理函数

abort

pthread_cancel

请求退出流的非正常退出


猜你喜欢

转载自blog.csdn.net/hualicuan/article/details/30047603
今日推荐