创建与终止线程

线程的管理常用的API有:

pthread_create(thread,attr,start_routine,arg)
pthread_exit(status)
pthread_cancel(thread)
pthread_attr_init(attr)
pthread_attr_destroy(attr)

创建线程:

  • 一个main程序包含一个默认的主线程,这个主线程在程序开始运行的时候由系统创建。除此之外的所有其他线程必须由程序员显式的创建。

  • pthread_create 创建一个可执行的线程。每次调用创建一个线程,同时,你可以在任何位置调用该函数。

  • pthread_create 参数:

    • thread:唯一标示一个新线程的用户不可见的标识符,由pthread_create产生
    • attr:一个线程的不可见的属性对象,可以用来设置新建线程的属性。可以传进一个线程属性对象,类型为pthread_attr_t;或者传NULL来使用默认值。
    • start_routine: 新线程创建好之后由新线程立即执行的子程序
    • arg:传给 start_routine的一个参数。它必须为void类型的指针,当然没有参数或者使用默认可以传NULL。如果想传进多个参数,可以它们封装进一个结构体。
  • 一个进程可以创建的线程数量的最大值在不同的系统内有不同的实现。

  • 在Linux查询和设置你的系统的线程数量限制方法如下:

  • bash / ksh / sh tcsh / csh
    $ ulimit -a
    core file size          (blocks, -c) 16
    data seg size           (kbytes, -d) unlimited
    scheduling priority             (-e) 0
    file size               (blocks, -f) unlimited
    pending signals                 (-i) 255956
    max locked memory       (kbytes, -l) 64
    max memory size         (kbytes, -m) unlimited
    open files                      (-n) 1024
    pipe size            (512 bytes, -p) 8
    POSIX message queues     (bytes, -q) 819200
    real-time priority              (-r) 0
    stack size              (kbytes, -s) unlimited
    cpu time               (seconds, -t) unlimited
    max user processes              (-u) 1024
    virtual memory          (kbytes, -v) unlimited
    file locks                      (-x) unlimited$ ulimit -Hu
    7168$ ulimit -u 7168$ ulimit -a
    core file size          (blocks, -c) 16
    data seg size           (kbytes, -d) unlimited
    scheduling priority             (-e) 0
    file size               (blocks, -f) unlimited
    pending signals                 (-i) 255956
    max locked memory       (kbytes, -l) 64
    max memory size         (kbytes, -m) unlimited
    open files                      (-n) 1024
    pipe size            (512 bytes, -p) 8
    POSIX message queues     (bytes, -q) 819200
    real-time priority              (-r) 0
    stack size              (kbytes, -s) unlimited
    cpu time               (seconds, -t) unlimited
    max user processes              (-u) 7168
    virtual memory          (kbytes, -v) unlimited
    file locks                      (-x) unlimited
    % limit
    cputime      unlimited
    filesize     unlimited
    datasize     unlimited
    stacksize    unlimited
    coredumpsize 16 kbytes
    memoryuse    unlimited
    vmemoryuse   unlimited
    descriptors  1024
    memorylocked 64 kbytes
    maxproc      1024% limit maxproc unlimited% limit
    cputime      unlimited
    filesize     unlimited
    datasize     unlimited
    stacksize    unlimited
    coredumpsize 16 kbytes
    memoryuse    unlimited
    vmemoryuse   unlimited
    descriptors  1024
    memorylocked 64 kbytes
    maxproc      7168
    
  • 一旦建立,线程之间是并行的,同时可以在线程内创建新的线程。线程之间没有继承或者依赖关系。

线程属性

  • 默认情况下,一个线程创建之后包含一些默认属性。其中一些可以由传递进去的线程属性对象改变。

  • pthread_attr_init 和 pthread_attr_destroy 用来初始化和销毁一个线程属性对象

  • 还有一些其他API可以用来查询或者设置线程属性对象中的特定的属性。线程的属性包括:

    • 分离或可结合状态
    • 调度继承
    • 调度策略
    • 调度参数
    • 调度竞争范围
    • 栈尺寸
    • 栈地址
    • 栈保护区大小

终止线程 pthread_exit():

  • 线程在以下几种情况下会终止:

    • 线程从其start_routine正常返回,其工作全部完成
    • 线程调用了pthread_exit(),无论其工作是否完成
    • 线程被其他线程通过调用pthread_cancel()取消
    • 线程所在的进程调用了exec() 或者 exit()
    • main()函数结束
  • pthread_exit()允许程序员指定一个可选的终止状态参数。这个可选的参数通常将返回线程“加入”终止线程。

  • pthread_exit()不会关闭文件,任何在线程内打开的文件在线程通过调用pthread_exit()终止后仍继续保持打开状态。

线程的创建和终止示例代码

  • 在这个简单的例子中将通过调用prhtread_ctreate()建立5个线程,每个线程输出“Hello World!”,然后调用pthread_exit()终止。这里是结果
  •  1 #include <pthread.h>
     2 #include <stdio.h>
     3 #define NUM_THREADS     5
     4
     5 void *PrintHello(void *threadid)
     6 {
     7    long tid;
     8    tid = (long)threadid;
     9    printf("Hello World! It's me, thread #%ld!\n", tid);
    10    pthread_exit(NULL);
    11 }
    12
    13 int main (int argc, char *argv[])
    14 {
    15    pthread_t threads[NUM_THREADS];
    16    int rc;
    17    long t;
    18    for(t=0; t<NUM_THREADS; t++){
    19       printf("In main: creating thread %ld\n", t);
    20       rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
    21       if (rc){
    22          printf("ERROR; return code from pthread_create() is %d\n", rc);
    23          exit(-1);
    24       }
    25    }
    26
    27    /* Last thing that main() should do */
    28    pthread_exit(NULL);
    29 }

向线程传递参数

  • pthread_create()允许传递一个参数到线程启动时调用的函数即所谓的start_routine。在需要传多个参数的时候,可以通过创建一个封装很多参数的结构体,然后将指向该结构体的指针传给 pthread_create()就可以了。

  • 所有的参数必须以指针形式传递,同时转为类型为void。

  • 线程传递参数的示例代码:这里是结果

  •  1 /******************************************************************************
     2 * FILE: hello_arg1.c
     3 * DESCRIPTION:
     4 *   A "hello world" Pthreads program which demonstrates one safe way
     5 *   to pass arguments to threads during thread creation.
     6 ******************************************************************************/
     7 #include <pthread.h>
     8 #include <stdio.h>
     9 #include <stdlib.h>
    10 #define NUM_THREADS    8
    11
    12 char *messages[NUM_THREADS];
    13
    14 void *PrintHello(void *threadid)
    15 {
    16    int *id_ptr, taskid;
    17
    18    sleep(1);
    19    id_ptr = (int *) threadid;
    20    taskid = *id_ptr;
    21    printf("Thread %d: %s\n", taskid, messages[taskid]);
    22    pthread_exit(NULL);
    23 }
    24
    25 int main(int argc, char *argv[])
    26 {
    27 pthread_t threads[NUM_THREADS];
    28 int *taskids[NUM_THREADS];
    29 int rc, t;
    30
    31 messages[0] = "English: Hello World!";
    32 messages[1] = "French: Bonjour, le monde!";
    33 messages[2] = "Spanish: Hola al mundo";
    34 messages[3] = "Klingon: Nuq neH!";
    35 messages[4] = "German: Guten Tag, Welt!";
    36 messages[5] = "Russian: Zdravstvytye, mir!";
    37 messages[6] = "Japan: Sekai e konnichiwa!";
    38 messages[7] = "Latin: Orbis, te saluto!";
    39
    40 for(t=0;t<NUM_THREADS;t++) {
    41   taskids[t] = (int *) malloc(sizeof(int));
    42   *taskids[t] = t;
    43   printf("Creating thread %d\n", t);
    44   rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskids[t]);
    45   if (rc) {
    46     printf("ERROR; return code from pthread_create() is %d\n", rc);
    47     exit(-1);
    48     }
    49   }
    50
    51 pthread_exit(NULL);
    52 }

传递多个参数的例子,请看这里

Joining and Detaching 线程

pthread_join(threadid,status)
pthread_detach(threadid)
pthread_attr_setdetachstate(attr,detachstate)
pthread_atr_getdetachstate(attr,detachstate)
  • Joining:

    • "Joining"是线程间同步的一种方式。

    • pthread_join()会阻塞调用的线程直至制定的threadid线程终止

    • 如果在指定的目标线程中调用pthread_exit(),程序员可以获得目标线程的终止返回状态。

    • 线程一个创建,其中的一个属性就被制定为joinable或者detached。而且只有joinable的线程才可以使用这种同步方式。

    • 显式的创建一个线程为joinable或者detached,可以在pthread_create()中使用属性参数,步骤如下: 1) 声明一个线程属性变量,类型为pthread_attr_t 2) 使用pthread_attr_init()初始化属性变量 3) 使用pthread_attr_setdetachstate()设置属性分离状态 4) 程序结束时,使用pthread_attr_destroy()释放属性对象使用的资源

    • 还有两种同步方法,互斥锁和条件变量,将在以后的blog中讨论

  • Detaching

    • pthread_detach()可以显式的detach一个线程即便它创建的时候是joinable。

    • 没有相反的API

  • Pthread Joining示例代码如下:这里是结果

     1 /*****************************************************************************
     2 * FILE: join.c
     3 * DESCRIPTION:
     4 *   This example demonstrates how to "wait" for thread completions by using
     5 *   the Pthread join routine.  Threads are explicitly created in a joinable
     6 *   state for portability reasons. Use of the pthread_exit status argument is
     7 *   also shown. Compare to detached.c
     8 ******************************************************************************/
     9 #include <pthread.h>
    10 #include <stdio.h>
    11 #include <stdlib.h>
    12 #define NUM_THREADS    4
    13
    14 void *BusyWork(void *t)
    15 {
    16    int i;
    17    long tid;
    18    double result=0.0;
    19    tid = (long)t;
    20    printf("Thread %ld starting...\n",tid);
    21    for (i=0; i<1000000; i++)
    22    {
    23       result = result + sin(i) * tan(i);
    24    }
    25    printf("Thread %ld done. Result = %e\n",tid, result);
    26    pthread_exit((void*) t);
    27 }
    28
    29 int main (int argc, char *argv[])
    30 {
    31    pthread_t thread[NUM_THREADS];
    32    pthread_attr_t attr;
    33    int rc;
    34    long t;
    35    void *status;
    36
    37    /* Initialize and set thread detached attribute */
    38    pthread_attr_init(&attr);
    39    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    40
    41    for(t=0; t<NUM_THREADS; t++) {
    42       printf("Main: creating thread %ld\n", t);
    43       rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t);
    44       if (rc) {
    45          printf("ERROR; return code from pthread_create() is %d\n", rc);
    46          exit(-1);
    47          }
    48       }
    49
    50    /* Free attribute and wait for the other threads */
    51    pthread_attr_destroy(&attr);
    52    for(t=0; t<NUM_THREADS; t++) {
    53       rc = pthread_join(thread[t], &status);
    54       if (rc) {
    55          printf("ERROR; return code from pthread_join() is %d\n", rc);
    56          exit(-1);
    57          }
    58       printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status);
    59       }
    60
    61 printf("Main: program completed. Exiting.\n");
    62 pthread_exit(NULL);
    63 }

转载于:https://www.cnblogs.com/nicganon/p/3735434.html

POSIX 线程编程(二)线程建立与终止相关推荐

  1. linux线程篇,linux线程篇 (二) 线程的基本操作

    线程 进程 标识符 pthread_t pid_t 获取ID pthread_self() getpid() 创建 pthread_create() fork 销毁 pthread_exit() ex ...

  2. 线程使用二——线程池

    线程池的作用: 线程池作用就是限制系统中执行线程的数量.      根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果:少了浪费了系统资源,多了造成系统拥挤效率不高.用线程池控制线程数 ...

  3. python线程任务run_python线程、进程知识梳理

    一.python线程 线程用于提供线程相关的操作,线程是应用程序中工作的最小单元. #!/ usr / bin / env python # - * - coding:utf-8 - * - impo ...

  4. Posix线程编程指南(4) 线程终止

    线程终止方式 一般来说,Posix的线程终止有两种情况:正常终止和非正常终止.线程主动调用pthread_exit()或者从线程函数中return都将使线程正常退出,这是可预见的退出方式:非正常终止是 ...

  5. 【多线程编程学习笔记6】终止线程执行,千万别踩这个坑!

    申明:本学习笔记是在该教程的基础上结合自己的学习情况进行的总结,不是原创,想要看原版的请看C语言中文网的多线程编程(C语言+Linux),该网站有很多好的编程学习教程,尤其是关于C语言的. 在< ...

  6. Posix多线程编程—线程属性

    一.线程属性 线程具有属性,用pthread_attr_t表示,在对该结构进行处理之前必须进行初始化,在使用后需要对其去除初始化.我们用pthread_attr_init函数对其初始化,用pthrea ...

  7. java 同步转并行_Java线程与并行编程(二)

    你好,我是goldsunC 让我们一起进步吧! 线程的控制与同步 线程的状态与生命周期 '每个Java程序都有一个默认的主线程,想要实现多线程,必须在主线程中创建新的线程对象.新建的线程在它的一个完整 ...

  8. python多线程并行编程_Python并行编程(二):基于线程的并行

    1.介绍 软件应用中使用最广泛的并行编程范例是多线程.通常一个应用有一个进程,分成多个独立的线程,并行运行.互相配合,执行不同类型的任务. 线程是独立的处理流程,可以和系统的其他线程并行或并发地执行. ...

  9. python多线程并行编程,Python并行编程(二):基于线程的并行

    1.介绍 软件应用中使用最广泛的并行编程范例是多线程.通常一个应用有一个进程,分成多个独立的线程,并行运行.互相配合,执行不同类型的任务. 线程是独立的处理流程,可以和系统的其他线程并行或并发地执行. ...

最新文章

  1. js、jquery相关的操作
  2. 世界上最美丽的23个公式
  3. 关于优酷开放SDK之setOnVideoSizeChangedListener
  4. onenetsim定位功能吗_经常玩手机的抓紧看看,原来手机键盘还隐藏4个实用功能,真实用...
  5. Java_基础—try...catch的方式处理异常1
  6. 怎么让网页中的文字两边留出空白_横线、方格、点阵、空白本,谁才是笔记本中的C位?...
  7. 串行设备造成鼠标乱跑的问题
  8. 一路风景之川藏线徒步笔记
  9. 锐浪报表 Grid++Report PrintPreview 显示模式
  10. win10天气是英文的
  11. word添加MathType插件
  12. hashcat详细使用教程
  13. python-爬取东方财富网期货市场大商所数据
  14. hdu2203java_HDU2203(KMP入门题)
  15. java ipmi 获取服务器硬件信息(温度,风扇转速,内存数,硬盘数等等)
  16. 为什么硬盘插在计算机上不显示,硬盘插在电脑上不显示怎么办
  17. 嵌入式linux与ARM开发板的入门建议
  18. 数组排序(O(n的二次方))
  19. 【每日新闻】2019年宏观经济展望!
  20. 懒人精灵(一款类似按键精灵的工具)制作和使用C/C++编写的插件

热门文章

  1. sqlserver 2008 R2 删除重复数据
  2. Android中的popupwindow从底部进入和退出的动画效果
  3. Android PopupWindow 隐藏软键盘的方法
  4. android 密码加密
  5. Android系统KeyStore (AndroidKeyStore): 存储密钥
  6. Widget(桌面插件)
  7. 一次失败的尝试,h5+Api 结合 react,webpack,同时生成android 、ios、h5端代码
  8. 智能检测营销是否合规,网易易盾发布广告合规检测解决方案
  9. (一)Linux基础(1)
  10. Pytorch模型迁移和迁移学习,导入部分模型参数