• POSIX多线程——基本线程管理函数介绍


    POSIX基本的几个线程管理函数见下表:
    ------------------------------------------------------------------------------------------
                         POSIX函数                                                         描述
    -------------------------------------------------------------------------------------------
                        pthread_create                                   创建一个线程
                        pthread_self                                       找出自己的线程ID
                        pthread_equal                                    测试2个线程ID是否相等
                        pthread_detach                                  设置线程以释放资源
                        pthread_join                                        等待一个线程
                        pthread_cancel                                   终止另一个线程
                        pthread_exit                                        退出线程,而不退出进程
                        pthread_kill                                         向线程发送一个信号
    -------------------------------------------------------------------------------------------
     
    (1)线程ID、获取和比较
    POSIX线程由一个pthread_t类型的ID来引用。线程可以通过调用pthread_self ()函数获得自己的线程ID,这里没有对pthread_self 定义错误。
     
    ==========================
    概要:
    #include <pthread.h>                     
    pthread_t   pthread_self (void);   
    ==========================
     
    由于pthread_t  可能是一个结构,所以不能由==来直接进行比较。这里可以使用函数pthread_equal()来比较线程ID是否相等,这里没有对pthread_equal定错误,如果两个线程ID相等,返回非0值,否则返回0.
     
    ============================================
    概要:
    #include <pthread.h>                     
    int   pthread_equal(pthread_t  t1, pthread_t  t2 );   
    ============================================
     
    (2)创建线程
    可以使用pthread_create()创建一个线程。POSIX的pthread_create()创建的线程是可以直接运行的,而不需要一个单独的启动操作。
     
    ==========================================
    概要:
    #include <pthread.h>
    int pthread_create(pthread_t *restrict thread,
                       const pthread_attr_t *restrict attr,
                       void *(*start_routine)(void *), 
                       void *restrict arg);
    ==========================================
    在上述函数中,thread指向新创建的线程ID;参数attr表示一个封装了线程各种属性的属性对象(比如栈大小、调度等信息,后面会专门介绍),如果attr为NULL,则使用默认属性进行创建;第三个参数start_routine是线程开始执行时调用的函数名字;第四个参数arg指针指向的数据是start_routine的参数。如果成功,函数返回0,否则返回非零错误码。
     
    下面例子中的代码就是连续创建10个线程,线程中执行的代码仅为打印自己的线程ID,和所属进程ID:
     
    #include <pthread.h>
    #include <stdio.h>
     
    void *print_thread(int *i)
    {
     fprintf(stderr,"number:%d,pid:%d,tid:%lld.
    ",*i,getpid(),(long long)pthread_self());
          return NULL;
    }
     
    int main(int argc, char* argv[ ] )
    {
     pthread_t tids[10];
     int i;
     for(i=0;i<10;i++)
     {
      if(pthread_create(&tids[i],NULL,print_thread,&i)==-1)
      {
       fprintf(stderr,"
    ERROR: fail to creat thread.");
       tids[i]= pthread_self();
      }
     }
     return 0;
    }
    执行结果:
    gaolu@gaolu-desktop:~$ ./thr
    number:0,pid:5579,tid:3085089680.
    number:1,pid:5579,tid:3076696976.
    number:2,pid:5579,tid:3068304272.
    number:3,pid:5579,tid:3059911568.
    number:4,pid:5579,tid:3051518864.
    number:5,pid:5579,tid:3043126160.
    number:6,pid:5579,tid:3034733456.
    number:7,pid:5579,tid:3026340752.
    number:8,pid:5579,tid:3017948048.
    number:9,pid:5579,tid:3009555344.
    gaolu@gaolu-desktop:~$
     
    (3)线程的分离(detach)和连接(join)
    一般情况下,线程在退出时,是不会释放它的资源的;
     
    如果将线程分离,即创建线程以后调用pthread_detach(tid)或者线程自身调用pthread_detach(pthread_self())都可以,它设置线程的内部选项来说明,线程退出以后存储空间可以被重新收回,分离线程退出时不会报告他们的状态。
     
    如果线程没有分离,那么它是可以接合(join)的,pthread_join和进程级别的函数wait_pid非常类似,该函数将调用线程挂起,直到第一个参数指定的目标线程终止为止。如果创建线程对子线程调用了pthread_join(), 子线程退出以后,资源在进程退出以后被回收。参数value_ptr为指向返回值的指针,这个返回值是目标线程return 或者传递给pthread_exit()的。
     
    为了防止内存泄漏,长时间运行的线程最终应该为每个线程调用pthread_join() 或者pthread_detach()。
     
    ===========================================
    概要:
    #include <pthread.h>
    int pthread_join(pthread_t th, void **value_ptr )
    int pthread_detach(pthread_t thread )
    ===========================================
     
    下面一个示例程序演示了pthread_detach和pthread_join之间的关系。
     
    (1)子线程将自己detach了,这种情况下线程是不能被join的。
    #include <pthread.h>
    #include <stdio.h>
    void *print_thread(void *ptr)
    {
     if(pthread_detach(pthread_self())==0)
     {
          fprintf(stderr,"tid:%lld,I have detached myself successfully.
    ",(long long)pthread_self( ) );
     }
     else
     {
          fprintf(stderr,"
    ERROR:detach failed.");
     }
          return NULL;
    }
    int main(int argc, char* argv[])
    {
     pthread_t tid;
     int *exitcode;
     if(pthread_create(&tid,NULL,print_thread,NULL)==-1)
     {
          fprintf(stderr,"
    ERROR: fail to creat thread.");
     }
     fprintf(stderr,"my pid is %d.
    ",getpid());
     if(pthread_join(tid,&exitcode)!=0)
     {
          fprintf(stderr,"ERROR: fail to join thread.
    ");
     }
     else
     {
          fprintf(stderr,"parent end successfully.
    ");
     }
     
     return 0;
    }
    gaolu@gaolu-desktop:~$ ./thr
    tid:3084360592,I have detached myself successfully.
    my pid is 5652.
    ERROR: fail to join thread.
    gaolu@gaolu-desktop:~$
     
    (2)修改创建的线程只是做了普通的打印信息,join可以执行成功。
    void *print_thread(void *ptr)
    {
         fprintf(stderr,"My tid:%lld. ",(long long)pthread_self());
    }
    gaolu@gaolu-desktop:~$ ./thr
    My tid:3085216656.
    my pid is 5702.
    parent end successfully.
    gaolu@gaolu-desktop:~$ 
    (4)线程退出和取消
    线程return一个指针value_ptr的相当于隐式地调用了pthread_exit(value_ptr)函数。如果进程的最后一个线程调用了pthread_exit,进程就会带着状态返回值0退出。
     
    对于一个被join了的线程来说,其返回值vlaue_ptr是可用的。也就是说value_ptr一定是要指向线程结束以后还存在的数据------这个问题可以通过几种方式解决:比如创建线程给被创建的线程传递参数时,参数中传递一个指针,作为被创建线程的返回值,这样返回值是位于创建线程的栈上;另外在被创建线程malloc内存,将指针作为返回值使用也可以。
     
    另外,线程可以通过取消机制迫使其他线程返回。线程通过执行pthread_cancel()来请求取消另一个线程,该函数在发出取消请求以后就返回了,而不需要阻塞;而实际结果由目标线程的类型和取消状态决定(状态可以通过函数设置的)。
     
    ==================================================
    概要:
    #include <pthread.h>
    int pthread_exit(void *value_ptr );
    int pthread_cancel( pthread_t thread );
    int pthread_setcancelstate (int state, int *oldstate);
    ==================================================
     
    如果线程收到cancel的请求时,处于PTHREAD_CANCEL_ENABLE,它就接受取消请求;否则如果处于PTHREAD_CANCEL_DISABLE的状态,取消请求就会被保持在挂起状态。默认情况下,线程处于PTHREAD_CANCEL_ENABLE状态。
     
     
     

    本文出自 “淡泊明志,宁静致远” 博客,请务必保留此出处http://keren.blog.51cto.com/720558/176759

  • 相关阅读:
    JQ购物车+1-1
    [转载]DATEDIFF() 函数返回两个日期之间的时间
    [转载]js获取当前页面url网址信息
    [转载]Request获取文件路径
    JQ页面跳转
    [转载]Sql Server 日期格式化函数
    [转载]jQuery的attr()与prop()的区别
    [转载]获取验证码60秒倒计时
    [转载]JQ键盘事件
    [转载]SQL常用语句
  • 原文地址:https://www.cnblogs.com/vinozly/p/5617871.html
Copyright © 2020-2023  润新知