一.概述:

    首先谈一下为什么要有线程。众所周知,一个进程只能进行一个执行流,虽然能创建子进程,但创建,终止,切换进程和进程间的通信的开销比较大,所以现代操作系统一般都使用线程。

    现在再谈一下我所了解的线程功能。一般可以这样认为,进程负责的是分配资源,而线程负责的是调度和执行。线程又叫轻量级进程。而传统的进程即负责分配资源,又承担一个线程的执行。

    进程和线程的区别:除了上面功能与性能的不同,还可以从进程管理的角度来区别。在单线程模型中,进程的表示包括它的进程控制块,用户地址空间,以及进程执行中管理调用/返回行为的用户栈,内核栈。在多线程环境中,进程只有一个与之关联的进程控制块和用户地址空间,而线程都有一个独立的栈,还有独立的控制块(包括寄存器,优先级和其它与线程相关的状态信息)。如下图:(摘自操作系统精髓与设计原理第4章)

注:如果在多处理器机器上,多线程的性能会更优。



二.相关函数:(PS:这里的线程库函数是由POSIX标准定义的,称为POSIX thread或者pthread。)

  1. pthread_create:     int  pthread_create(pthread_t *pthread, const pthread_attr_t *attr,

                                                                        void *(*start_toutine)(void *),  void *arg)

函数功能:创建一个线程,使线程从传入的函数指针所指的函数中开始执行。

pthread参数:输出型参数,创建成功会把线程id放入里面。

attr参数:用来设置线程的属性,如线程的分离状态属性,线程栈的大小等。一般为NULL就可以了。

start_toutine参数:函数指针,用于指明线程从哪里开始执行。

arg参数:传入函数指针所指的函数的参数。

返回值:所有pthread函数都是成功返回0,失败返回一个错误号。可以用strerror显示错误号。

PS:主线程会从函数返回出继续往下执行。

   2.pthread_exit:void pthread_exit(void *retval)

函数功能:线程可以调用自己进行注销操作。

retval参数:退出时返回的值。

   3.pthread_cancel:int  pthread_cancel(pthread_t  pthread)

函数功能:注销线程id为pthread的线程。

返回值:成功返回0,失败返回一个错误号。

  4.pthread_join:int  pthread_join(pthread_t pthread, void** retval)

函数功能:将线程id为pthread的线程挂起等待,直到线程终止,终止状态保持到retval中。

retval参数:输出型参数,用于保存线程终止的终止状态。不同的终止方法有不同的终止状态:

(1).如果线程通过return返回,retval中指向的单元里存放的是线程函数的返回值。

(2).如果线程被别的线程调用pthread_cancel异常终止,retval指向的单元中存放的是常数PTHREAD_CALCELED。

(3).如果线程自己调用pthread_exit()函数终止的,retval指向的单元中存放的是传给pthead_exit()的参数。

返回值:成功返回0,失败返回一个错误号。



三.相关代码:(PS:编译时要加    -Lpthread)

  1. 创建一个进程:

1 #include
                                                                                                                                                2 #include
  3 #include
  4   5 pthread_t tid;  6   7 void* create_thread(void *ptr)  8 {  9     printf("%s . pid is:%d  tid is:%ul \n",(char *)ptr, (int)getpid(), (unsigned long long)pthread_self()); 10     return NULL; 11 } 12  13 int main() 14 { 15     int err = pthread_create(&tid, NULL, create_thread, "i'm a thread"); 16     if(err != 0) 17     { 18         printf("create thread failed! info is :%s", strerror(err)); 19         exit(err); 20     } 21  22     printf("main thread run. pid is:%d  tid is:%ul \n", (int)getpid(), (unsigned long long)pthread_self());//linux 下tid为一个地址值 23     sleep(1); 24     return 0; 25 }

执行结果:

2.线程等待:

 1 #include
                                                                                                                                                2 #include
  3 #include
  4   5 void *create_thread1(void *ptr)  6 {  7     printf("this is thread1\n");  8     return (void *)1;  9 } 10  11 void *create_thread2(void *ptr) 12 { 13     printf("this is thread2\n"); 14     pthread_exit((void *)2); 15 } 16  17 void *create_thread3(void *ptr) 18 { 19     while(1) 20     { 21         printf("this is thread3,waiting for be calceled.....\n"); 22         sleep(1); 23     } 24     return NULL; 25 } 26  27 int main() 28 { 29     pthread_t tid; 30     void* ret; 31  32     int err1 = pthread_create(&tid, NULL, create_thread1, NULL); 33     if(err1 != 0) 34     { 35         printf("create thread failed!"); 36     } 37     pthread_join(tid, &ret); 38     printf("thread is returned,tid is:%ul return code is:%d \n", (unsigned long long)pthread_self(), (int)ret); 39  40     int err2 = pthread_create(&tid, NULL, create_thread2, NULL); 41     if(err2 != 0) 42     { 43         printf("create thread failed!"); 44     } 45     pthread_join(tid, &ret); 46     printf("thread is exited,tid is:%ul return code is:%d \n", (unsigned long long)pthread_self(), (int)ret); 47  48     int err3 = pthread_create(&tid, NULL, create_thread3, NULL); 49     if(err3 != 0) 50     { 51         printf("create thread failed!"); 52     } 53     sleep(3); 54     pthread_cancel(tid); 55     pthread_join(tid, &ret); 56     printf("thread is canceled,tid is:%ul return code is:%d \n", (unsigned long long)pthread_self(), (int)ret); 57  58     return 0; 59 }

执行结果: