zoukankan      html  css  js  c++  java
  • UNIX环境编程学习笔记(26)——多线程编程(一):创建和终止线程

    lienhua34
    2014-11-08

    进程控制三部曲中我们学习了进程的创建、终止以及获取终止状态等的进程控制原语。线程的控制与进程的控制有相似之处,在表 1中我们列出了进程和线程相对应的控制原语。

    表 1: 进程原语和线程原语的比较
    进程原语 线程原语 描述
    fork pthread_create 创建新的控制流
    exit pthread_exit 从现有的控制流中退出
    waitpid pthread_join 从控制流中得到退出状态
    atexit pthread_cleanup_push 注册在退出控制流时调用的函数
    getpid pthread_self 获取控制流的 ID
    abort pthread_cancel 请求控制流的非正常退出

    1 线程

    每个线程都有一个线程 ID,线程只在它所属的进程环境中有效。线程ID 使用pthread_t 表示。可以通过调用pthread_self 函数获取线程自身的线程 ID,

    #include <pthread.h>

    pthread_t pthread_self(void);

    返回值:调用线程的线程ID

    线程 ID 不一定是一个非负整数,也有可能是一个结构体。所以,要对比两个线程是否相同,必须使用pthread_equal 函数来进行,

    #include <pthread.h>

    int pthread_equal(pthread_t tid1, pthread_t tid2);

    返回值:若相等则返回非0值,否则返回0

    2 线程的创建

    可以通过调用pthread_create 来创建新的线程,

    #include <pthread.h>

    int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);

    返回值:若成功则返回0,否则返回错误编码

    其中,参数 tidp 用于返回成功创建的新线程的线程 ID。参数 attr 用于定制各种不同的线程属性,如果设置为 NULL,表示创建一个默认属性的线程。成功创建的新线程将从参数start_rtn 所指向的函数开始执行,该函数接收一个 void * 的参数 arg,并返回一个 void * 的返回值。

    注意:pthread_create 失败的时候返回的是错误编码,表示我们可以通过调用 strerror 函数来获取具体的错误信息。

    下面我们来看一个创建新进程的例子,

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <pthread.h>
    
    void *
    my_thread(void *arg)
    {
      printf("in new thread. tid: %u
    ", (unsigned int)pthread_self());
      return ((void *)0);
    }
    
    int
    main(void)
    {
      int err;
      pthread_t tid;
    
      err = pthread_create(&tid, NULL, my_thread, NULL);
      if ( err != 0) {
        printf("can't create thread: %s
    ", strerror(err));
        exit(-1);
      }
      printf("in main thread: %u
    ", (unsigned int)pthread_self());
      sleep(1);
      exit(0);
    }

    编译该程序,生成并执行文件pthread_create_demo。从下面的运行结果,我们可以看到在 main 函数和my_thread 函数打印的线程 ID 是不一样的。

    lienhua34:demo$ gcc -o pthread_create_demo -pthread pthread_create_demo.c
    lienhua34:demo$ ./pthread_create_demo
    in main thread: 3076478720
    in new thread. tid: 3076475712

    3 线程终止

    如果进程中的任一线程调用了exit、_Exit 或_exit 函数,那么整个进程都将会终止。那如果我们只是想单独的终止一个线程呢?有三种方式,

    1. 线程从启动例程中返回,返回值即为线程的退出码。

    2. 被同一个进程中的其他线程取消。

    3. 线程调用函数pthread_exit。

    pthread_exit 函数的声明如下,

    #include <pthread.h>

    void pthread_exit(void *rval_ptr);

    进程中其它线程可以通过调用pthread_join 来获取指定线程的退出码。

    #include <pthread.h>

    int pthread_join(pthread_t tid, void **rval_ptr);

    返回值:若成功则返回0,否则返回错误编号

    pthread_join 函数会使调用线程一直阻塞,直到指定的线程终止。如果指定线程只是从它的启动例程中返回,rval_ptr 将包含返回码。如果线程被取消,由rval_ptr 指定的内存单元将被置为PTHREAD_CANCELED。

    下面我们来看一个线程终止的例子,

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <pthread.h>
    
    void *
    thr_fn1(void *arg)
    {
      printf("in thread 1
    ");
      return ((void *)1);
    }
    
    void *
    thr_fn2(void *arg)
    {
      printf("in thread 2
    ");
      pthread_exit((void *)2);
    }
    
    int
    main(void)
    {
      int err;
      pthread_t tid1, tid2;
      void *tret;
      
      err = pthread_create(&tid1, NULL, thr_fn1, NULL);
      if ( err != 0) {
        printf("can't create thread 1: %s
    ", strerror(err));
        exit(-1);
      }
    
      err = pthread_create(&tid2, NULL, thr_fn2, NULL);
      if (err != 0) {
        printf("can't create thread 2: %s
    ", strerror(err));
        exit(-1);
      }
    
      err = pthread_join(tid1, &tret);
      if (err != 0) {
        printf("can't join with thread 1: %s
    ", strerror(err));
        exit(-1);
      }
      printf("thread 1 exit code: %d
    ", (int)tret);
    
      err = pthread_join(tid2, &tret);
      if (err != 0) {
        printf("can't join with thread 2: %s
    ", strerror(err));
        exit(-1);
      }
      printf("thread 2 exit code: %d
    ", (int)tret);
      
      exit(0);
    }
    pthread_exit_demo.c

    编译该程序,生成并执行文件pthread_exit_demo,

    lienhua34:demo$ gcc -o pthread_exit_demo -pthread pthread_exit_demo.c
    lienhua34:demo$ ./pthread_exit_demo
    in thread 1
    in thread 2
    thread 1 exit code: 1
    thread 2 exit code: 2

    (done)

  • 相关阅读:
    深度学习工具
    rcnn学习(六):imdb.py学习
    r-cnn学习(六):RPN及AnchorTargetLayer学习
    r-cnn学习(五):SmoothL1LossLayer论文与代码的结合理解
    liunx学习(一):linux下目录操作大全
    Caffe学习系列(17): blob
    r-cnn学习(四):train_faster_rcnn_alt_opt.py源码学习
    faster r-cnn 在CPU配置下训练自己的数据
    R-FCN、SSD、YOLO2、faster-rcnn和labelImg实验笔记(转)
    如何学习caffe
  • 原文地址:https://www.cnblogs.com/lienhua34/p/4084334.html
Copyright © 2011-2022 走看看