• 【线程】多线程创建,传参,共享数据,终止,等待,清除


    多线程优点

      使用线程的理由之一:

      和进程相比,它是一种“节俭”的多任务操作方式。在linux系统下,启动一个新的进程必须分配给他独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种“昂贵的”多任务工作方式。

    运行于一个进程中的多个线程,他们之间使用相同的地址空间,而且线程间彼此切换所用的时间也远远小于进程间切换所用的时间。据统计,一个进程的开销大约是一个线程开销的30倍左右。

      使用多线程理由之二:

      线程间方便的通信机制。对不同进程来说,他们具有独立的数据空间,要进行数据传递只能通过进程间通信的方式进行,这种方式不仅耗时而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。

      除了以上优点之外,多线程作为一种多任务、并发的工作方式,有如下优点:

      使多CPU系统更加有效,操作系统会保证当线程数不大于CPU数目时,不同的线程运行在不同的CPU上。

      改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或者半独立的部分,这样的程序会有利于理解和修改。

    创建线程

    #include<pthread.h>
    int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,void *(*start_rtn)(void),void arg)
    • tidp:线程ID
    • attr:线程属性(通常为空)
    • start_rtn:线程要执行的函数
    • arg:start_rtn的参数

    编译

      因为pthread的库不是LINUX系统库,所以在编译的时候要加上  -lphread

    #gcc filename -lphread -o 。。。

      

    线程实例之pthread_join()

     1 /********************************************************** 
     2 *程序要求:   在程序中创建一个线程,进程需等待该线程执行结束后才能继续执行。 
     3 *功能描述:   通过pthread_join阻塞等待,直至相应线程结束。 
     4 **********************************************************/  
     5 #include <unistd.h>  
     6 #include <stdio.h>  
     7 #include <pthread.h>  
     8   
     9 /* 
    10 * 线程的执行函数 
    11 * */  
    12 void *thread(void *str)  
    13 {  
    14     int i;  
    15     for (i = 0; i < 3; ++i)  
    16     {  
    17         sleep(2);  
    18         printf( "This in the thread : %d
    " , i );  
    19     }  
    20     return NULL;  
    21 }  
    22   
    23   
    24 /* 
    25 * 程序入口 
    26 * */  
    27 int main()  
    28 {  
    29     pthread_t pth;  
    30     int i;  
    31   
    32     /*创建线程并执行线程执行函数*/  
    33     int ret = pthread_create(&pth, NULL, thread, NULL);    
    34     printf("The main process will be to run,but will be blocked soon
    ");     
    35     /*阻塞等待线程退出*/  
    36     pthread_join(pth, NULL);  
    37   
    38     printf("thread was exit
    ");  
    39     for (i = 0; i < 3; ++i)  
    40     {  
    41         sleep(1);  
    42         printf( "This in the main : %d
    " , i );  
    43     }  
    44     return 0;  
    45 }  
    View Code

      

    线程实例之传参 

     1 #include <unistd.h>  
     2 #include <stdio.h>  
     3 #include <pthread.h>  
     4   
     5 /* 
     6 * 线程的执行函数 
     7 * */  
     8 void *thread(void *str)  
     9 {  
    10     int *num;  
    11     num=(int *)str;  
    12     printf("create parameter is %d
    ",*num);  
    13     return (void*)0;  
    14       
    15 }  
    16   
    17   
    18 /* 
    19 * 程序入口 
    20 * */  
    21 int main()  
    22 {  
    23     pthread_t pth;  
    24     int error;  
    25     int test=4;  
    26     int *attr=&test;  
    27   
    28     /*创建线程并执行线程执行函数*/  
    29     error = pthread_create(&pth, NULL, thread, (void *)attr);    
    30     if(error)  
    31     {  
    32         printf("pthread_create is created is not create...
    ");  
    33         return -1;  
    34     }  
    35     sleep(1);  
    36   
    37     printf("pthread_create is created
    ");  
    38       
    39     return 0;  
    40 }  
    View Code

    线程实例之传结构体

     1 /********************************************************** 
     2 *实验要求:   在程序中创建一个线程,并向该线程处理函数传递一个结构体作为 
     3 *           参数。 
     4 *功能描述:   通过pthread_create创建一个线程并传入一个结构体参数,再 
     5 *           在线程中接收到这个参数并把参数内容打印出来。 
     6 **********************************************************/  
     7 #include <stdio.h>  
     8 #include <unistd.h>  
     9 #include <stdlib.h>  
    10 #include <pthread.h>  
    11   
    12 struct menber  
    13 {  
    14     int a;  
    15     char *s;  
    16 };  
    17   
    18 /* 
    19  * 线程执行函数 
    20  * */  
    21 void *create(void *arg)  
    22 {  
    23     struct menber *temp;  
    24     temp=(struct menber *)arg;  
    25     
    26     printf("menber->a = %d  
    ",temp->a);  
    27     printf("menber->s = %s  
    ",temp->s);  
    28     
    29     return (void *)0;  
    30 }  
    31   
    32 /* 
    33  * 程序入口 
    34  * */  
    35 int main(int argc,char *argv[])  
    36 {  
    37     pthread_t tidp;  
    38     int error;  
    39     struct menber *b;  
    40   
    41     /*为结构体指针b分配内存并赋值*/  
    42     b=(struct menber *)malloc( sizeof(struct menber) );  
    43     b->a = 4;  
    44     b->s = "成鹏致远";  
    45       
    46     /*创建线程并运行线程执行函数*/  
    47     error = pthread_create(&tidp, NULL, create, (void *)b);  
    48     if( error )  
    49     {  
    50         printf("phread is not created...
    ");  
    51         return -1;  
    52     }  
    53   
    54     sleep(1); //进程睡眠一秒使线程执行完后进程才会结束  
    55   
    56     printf("pthread is created...
    ");  
    57     return 0;  
    58 }  
    View Code

      

    线程实例之共享进程数据

     1 /********************************************************** 
     2 *程序要求:   在程序中创建一个线程,进程需等待该线程执行结束后才能继续执行。 
     3 *功能描述:   创建的线程和创建线程的进程是共享数据段中的数据。 
     4 **********************************************************/  
     5 #include <unistd.h>  
     6 #include <stdio.h>  
     7 #include <pthread.h>  
     8   
     9 /* 
    10 * 线程的执行函数 
    11 * */  
    12 int a=1;   /*存放在数据段当中的数据*/  
    13 
    14 void *thread(void *str)  
    15 {  
    16     printf("new pthread ...
    ");  
    17     printf("a=%d 
    ",a);  
    18     a++;  
    19     return (void *)0;  
    20 }  
    21   
    22   
    23 /* 
    24 * 程序入口 
    25 * */  
    26 int main()  
    27 {  
    28     pthread_t pth;  
    29     int error;  
    30       
    31       
    32     printf("in main 1: a=%d",a);  
    33   
    34     /*创建线程并执行线程执行函数*/  
    35     error = pthread_create(&pth, NULL, thread, NULL);  
    36     if(error!=0)  
    37     {  
    38         printf("new pthread is not created ...
    ");  
    39         return -1;  
    40     }  
    41     sleep(3);  
    42       
    43     printf("in main 2: a=%d",a);  
    44     printf("new thread is create...
    ");  
    45       
    46     return 0;  
    47 }  
    View Code

      注意:线程会共享创建线程的进程中的内容,并且共享的是数据段的内容,而不能是栈里面的内容。

    终止线程

      如果进程中任何一个线程中调用exit或_exit,那么整个进程都会终止,线程的正常终止方式有:

    1. 线程从启动例程中返回return。
    2. 线程可以被另一个进程终止(kill)。
    3. 线程自己调用pthread_exit函数。
    #inlucde<pthread.h>
    void pthread_exit(void *rval_ptr)

      

      功能:终止调用线程。

      Rval_ptr:线程退出返回值的指针。

    线程等待

    #include<pthread.h>
    int pthread_join(pthread_t tid,void **rval_ptr)

      

      功能:阻塞调用线程,直到指定的线程终止。

      Tid:等待退出的线程ID

      Rval_ptr:线程退出的返回值的指针。

    线程的清除

      线程终止有两种情况:正常终止和非正常终止。

      线程主动调用pthread_exit或者从线程函数中return都将使得线程正常终止,这是可以预见的退出方式;非正常终止是线程在其他线程的干预下,或者由于自身运行错误而退出,这种退出方式不可预见的。

      在非正常或者正常终止条件下,如何释放资源,是一个必须考虑的问题。

      从pthread_cleanup_push的调用点到pthread_cleanup_pop之间的程序段中的终止动作(包括调用pthread_exit()和异常终止,不包括return)都将执行pthread_cleanup_push()所指定的清理函数。

    #include<pthread.h>
    void pthread_cleanup_push(void(*rtn)(void *),void *arg)

      功能:将清除函数压入栈

    • rtn:清除函数
    • arg:清除函数参数
    #include<pthread.h>
    void pthread_cleanup_pop(int execute) 

      功能:将清除函数弹出清除栈

      参数:execute执行到pthread_cleanup_pop时是否在弹出清理函数的同时执行该函数,非0:执行,0:不执行。

    线程实例之清除程序

      1 /**********************************************************
      2 *实验要求:   在程序中创建一个线程,使用线程API对该线程进行清理工作。
      3 *功能描述:   创建线程,并在其中使用函数pthread_cleanup_push和函数
      4 *           pthread_cleanup_pop,验证这两个清理函数的效果。
      5 **********************************************************/
      6 #include <stdio.h>
      7 #include <pthread.h>
      8 #include <unistd.h>
      9 
     10 /*
     11  * 线程清理函数
     12  * */
     13 void *clean(void *arg)
     14 {
     15     printf("cleanup :%s
    ",(char *)arg);
     16     
     17     return (void *)0;
     18 }
     19 
     20 /*
     21  * 线程1的执行函数
     22  * */
     23 void *thr_fn1(void *arg)
     24 {
     25     printf("thread 1 start  
    ");
     26     /*将线程清理函数压入清除栈两次*/
     27     pthread_cleanup_push( (void*)clean,"thread 1 first handler");
     28     pthread_cleanup_push( (void*)clean,"thread 1 second hadler");
     29     printf("thread 1 push complete  
    ");
     30 
     31     if(arg)
     32     {
     33         return((void *)1); //线程运行到这里会结束,后面的代码不会被运行。由于是用return退出,所以不会执行线程清理函数。
     34     }
     35     pthread_cleanup_pop(0);
     36     pthread_cleanup_pop(0);
     37     
     38     return (void *)1;
     39 }
     40 
     41 /*
     42  * 线程2的执行函数
     43  * */
     44 void *thr_fn2(void *arg)
     45 {
     46     printf("thread 2 start  
    ");
     47 
     48     /*将线程清理函数压入清除栈两次*/
     49     pthread_cleanup_push( (void*)clean,"thread 2 first handler");
     50     pthread_cleanup_push( (void*)clean,"thread 2 second handler");
     51     printf("thread 2 push complete  
    ");
     52     
     53     if(arg)
     54     {
     55         pthread_exit((void *)2);//线程运行到这里会结束,后面的代码不会被运行。由于是用pthread_exit退出,所以会执行线程清理函数。执行的顺序是先压进栈的后执行,即后进先出。
     56     }
     57     pthread_cleanup_pop(0);
     58     pthread_cleanup_pop(0);
     59     pthread_exit((void *)2);
     60 }
     61 
     62 /*
     63  * 程序入口
     64  * */
     65 int main(void)
     66 {
     67     int err;
     68     pthread_t tid1,tid2;
     69     void *tret;
     70 
     71     /*创建线程1并执行线程执行函数*/
     72     err=pthread_create(&tid1,NULL,thr_fn1,(void *)1);
     73     if(err!=0)
     74     {
     75         printf("error .... 
    ");
     76         return -1;
     77     }
     78     /*创建线程2并执行线程执行函数*/
     79     err=pthread_create(&tid2,NULL,thr_fn2,(void *)1);
     80     if(err!=0)
     81     {
     82         printf("error .... 
    ");
     83         return -1;
     84     }
     85 
     86     /*阻塞等待线程1退出,并获取线程1的返回值*/
     87     err=pthread_join(tid1,&tret);
     88     if(err!=0)
     89     {
     90         printf("error .... 
    ");
     91         return -1;
     92     }
     93     printf("thread 1 exit code %d  
    ",(int)tret);
     94     /*阻塞等待线程2退出,并获取线程2的返回值*/
     95     err=pthread_join(tid2,&tret);
     96     if(err!=0)
     97     {
     98         printf("error .... ");
     99         return -1;
    100     }
    101     printf("thread 2 exit code %d  
    ",(int)tret);  
    102     
    103     return 1;
    104 }
    View Code

    运行结果

    1 thread 1 start  
    2 thread 1 push complete  
    3 thread 1 exit code 1  
    4 thread 2 start  
    5 thread 2 push complete  
    6 cleanup :thread 2 second handler
    7 cleanup :thread 2 first handler
    8 thread 2 exit code 2  
    View Code
  • 相关阅读:
    JAVA获取随机数
    web路径问题
    java.lang.IllegalStateException: Failed to load ApplicationContext,这个异常的解决方案
    使用表达式配置切入点
    Spring的aop操作
    AOP操作术语
    AOP原理
    AOP概念
    spring知识点
    Spring的ioc操作 与 IOC底层原理
  • 原文地址:https://www.cnblogs.com/lcw/p/3236418.html
Copyright © 2020-2023  润新知