一.概述:

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

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

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

wKiom1cXPhmyxf7BAAJFuLVRCC4814.png

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




二.相关函数:(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<stdio.h>                                                                                                                                              
  2 #include<stdlib.h>
  3 #include<pthread.h>
  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 }

执行结果:

wKiom1cWMEXDM0elAAA1CwtyzGo668.png


2.线程等待:

 1 #include<stdio.h>                                                                                                                                              
  2 #include<stdlib.h>
  3 #include<pthread.h>
  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 }

执行结果:

wKiom1cWPnLQqc_rAAA-Ol4ljcQ597.png