zoukankan      html  css  js  c++  java
  • linux多进/线程编程(7)——多线程1(线程的创建,回收,分离,设置线程属性等)

    参考资料:

    1.博客1:https://blog.csdn.net/zhou1021jian/article/details/71531699

     2.博客2:https://blog.csdn.net/weixin_40039738/article/details/81145247

    本文主要介绍下面函数的用法和代码示例

    pthread_create            创建线程
    pthread_exit             终止线程
    pthread_join             回收进程
    pthread_detach           线程分离
    pthread_attr_setdetachstate   设置线程属性

    注意:在linux下查看线程相关的方法时,man 出来可以非常多,所以要想查阅资料搞清楚到底需要啥

    pthread_create 创建线程

    函数原型:

    #include <pthread.h>
    
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

    创建出的新线程退出的可能情况:

    * It calls pthread_exit(3), specifying an exit status value that is available to another thread in the same process that calls pthread_join(3).
    
    * It returns from start_routine().  This is equivalent to calling pthread_exit(3) with the value supplied in the return statement.
    
    * It is canceled (see pthread_cancel(3)).
    
    * Any of the threads in the process calls exit(3), or the main thread performs a return from main().  

    简言之就是以下几种可能:
    1.执行新线程的函数“走完了”;
    2.新线程本身或者与之join的线程执行“终止线程”的方法pthread_exit;
    3.取消创建该线程pthread_cancel;
    4.其他线程执行推出exit,或者主线程return弹(函数)栈

    pthread_exit 终止进程

    终止调用它的线程并返回一个指向某个对象的指针。

    创建进程 代码示例:

    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    
    void* thr(void* arg) {
      printf("i am a thread! pid = %d, tid = %ld
    ", getpid(), pthread_self());
      //pthread_exit((void*)100);
    //  return nullptr;
    }
    
    int main(int argc, char* argv[]) {
      /*
       * int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                              void *(*start_routine) (void *), void *arg);
      */
    
      pthread_t tid { 0 };
      pthread_create(&tid, nullptr, thr, nullptr);
      printf("i am a main thread! pid = %d, tid = %ld
    ", getpid(), pthread_self());
    
      //sleep(1);
      /*1. 如果添加pthread_exit()在主线程,则主线程马上退出,不在执行主线程下面的程序,但是主线程中启动的其他线程继续执行,程序不会马上退出,等待子线程执行完毕退出。
      2. 如果不添加,主线程不等待子线程执行完毕,程序直接退出,子线程可能没有执行完毕。*/
      pthread_exit(nullptr);
    
      //return 0;// no use, never exec
    }

    线程joinable

    上面的代码中子线程创建成功依赖于,主线程要么是推出的很慢(有耗时操作)来保证一定会创建子线程,要么是加上pthread_exit,我们往往不想这么做,因此介绍
    pthread_join  

    pthread_join

    函数原型:

    #include <pthread.h>
    
    int pthread_join(pthread_t thread, void **retval);

    描述:

    The  pthread_join() function  waits for the thread specified by thread to terminate. wait()方法用来回收进程,是阻塞的,类比,pthread_join也是阻塞的,直至指定的进程终止才会执行后面的代码。
    
    If that thread has already terminated, then pthread_join() returns immediately.  
    
    The thread specified by thread must be joinable.

    代码示例:

    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <stdlib.h>
    
    void* thr(void* arg) {
      printf("i am a thread! pid = %d, tid = %ld
    ", getpid(), pthread_self());
      sleep(3);
      pthread_exit((void*)1004);
    //  return (void*)100;
    }
    
    int main(int argc, char* argv[]) {
      /*
       * int pthread_join(pthread_t thread, void **retval);
      */
      pthread_t tid { 0 };
      pthread_create(&tid, nullptr, thr, nullptr);
      printf("i am a main thread! pid = %d, tid = %ld
    ", getpid(), pthread_self());
    
      void* ret = nullptr;
      pthread_join(tid, &ret);//回收子线程,pthread_join会阻塞,直到子线程退出
      printf("ret exit with %ld
    ", (long)ret);
    
      //sleep(1);
      /*
       * 此处主线程加pthread_exit仅用来回收主线程,不影响子线程创建,因为pthread_join的作用*/
      pthread_exit(nullptr);
    
       //return 0; no use there
    }

    线程detached

    线程默认属性就是joinable,依赖于创建该线程的“父线程”(其实线程之间不存在父子关系),但是可以修改线程属性。

    修改方法有两种,1是使用函数pthread_detach,2是设置属性pthread_attr_setdetachstate。

    当线程被分离(detached)后,这个线程的回收就交给操作系统,就不是用户可以控制的了。

    pthread_detach

    函数原型:

    #include <pthread.h>
    
    int pthread_detach(pthread_t thread);

    描述:

    The  pthread_detach()  function  marks the thread identified by thread as detached.  

    When a detached thread terminates, its resources are automatically released back to the system without the
    need
    for another thread to join with the terminated thread.

    pthread_attr_setdetachstate

    函数原型:

    #include <pthread.h>
    
    int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
    int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);

    描述:

    The  pthread_attr_setdetachstate()  function  sets  the  detach  state  attribute  of the thread attributes object referred to by attr to the value specified in detachstate.  

    The detach state attribute determines whether a thread created using the thread attributes object attr will be created in a joinable or a detached state.
    The following values may be specified in detachstate: PTHREAD_CREATE_DETACHED
    Threads that are created using attr will be created in a detached state. PTHREAD_CREATE_JOINABLE Threads that are created using attr will be created in a joinable state. The default setting of the detach state attribute in a newly initialized thread attributes object is PTHREAD_CREATE_JOINABLE.(默认是joinable,可以设置为detached The pthread_attr_getdetachstate() returns the detach state attribute of the thread attributes object attr in the buffer pointed to by detachstate.

    代码示例:

    #include <stdio.h>
    #include <pthread.h>
    #include <string.h>
    
    void * thr(void * arg) {
      printf("i am child thread 
    ");
      return nullptr;
    }
    
    int main(int argc, char* argv[]) {
      
      pthread_attr_t attr;
      pthread_attr_init(&attr);
      /*
       * 当设置为PTHREAD_CREATE_JOINABLE时,下面可以用pthread_join回收,但是如果设置为PTHREAD_CREATE_DETACHED则不可以
       * */
      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    
      pthread_t tid {0};
      pthread_create(&tid, &attr, thr, nullptr);
      
      int ret = 0;
      if ((ret = pthread_join(tid, nullptr)) > 0) {
        //printf("join err:%ld, %s
    ", (long)ret, strerror((long)ret));
        printf("join err:%d, %s
    ", ret, strerror(ret));
      }
    
      pthread_attr_destroy(&attr);
    
      return 0;
    }

    其他代码:

    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    
    void * thr(void * arg) {
    
    //  malloc();
      printf("i am child thread, tid = %ld, arg = %ld
    ", pthread_self(), (long)arg);
      //return nullptr;
      return (void *)(100 + (long)arg);
    }
    
    int main(int argc, char* argv[]) {
    
      pthread_t tid[5];
    
      int length = sizeof(tid) / sizeof(pthread_t);
    
      printf("**********************length = %d
    ", length);
    
      for (long i = 0; i < length; ++i) {
        /* (void*)i :
         * 这里不能这样写,最好是先在堆区创建,再传进去,用完了在外面释放,这样保证数据没问题。
         * 如果直接传地址,可能在创建子线程的过程中,数据发生了变化(指向的地址也变了),这样传参不稳定,有问题。
         * */
        pthread_create(&tid[i], nullptr, thr, (void*)i);
      }
    
      for (int i = 0; i < length; ++i) {
        void* ret = nullptr;
        pthread_join(tid[i], &ret);
        printf("i == %d, ret == %ld
    ", i, (long)ret);
      }
    
      return 0;
    }
  • 相关阅读:
    jquery选择器(复习向)
    如何使元素/文字 垂直居中?
    mvc与mvvm的区别与联系
    python16_day26【crm 增、改、查】
    python16_day25【crm】
    python16_day24【restful、crm表构、认证】
    python16_day23【cmdb前端】
    django 【认证】
    python16_day22【cmdb注释】
    django【F和Q】
  • 原文地址:https://www.cnblogs.com/kongweisi/p/14695099.html
Copyright © 2011-2022 走看看