创建与终止线程

线程的管理常用的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()终止。这里是结果
  •  #include <pthread.h>
    #include <stdio.h>
    #define NUM_THREADS 5 void *PrintHello(void *threadid)
    {
    long tid;
    tid = (long)threadid;
    printf("Hello World! It's me, thread #%ld!\n", tid);
    pthread_exit(NULL);
    } int main (int argc, char *argv[])
    {
    pthread_t threads[NUM_THREADS];
    int rc;
    long t;
    for(t=; t<NUM_THREADS; t++){
    printf("In main: creating thread %ld\n", t);
    rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
    if (rc){
    printf("ERROR; return code from pthread_create() is %d\n", rc);
    exit(-);
    }
    } /* Last thing that main() should do */
    pthread_exit(NULL);
    }

向线程传递参数

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

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

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

  •  /******************************************************************************
    * FILE: hello_arg1.c
    * DESCRIPTION:
    * A "hello world" Pthreads program which demonstrates one safe way
    * to pass arguments to threads during thread creation.
    ******************************************************************************/
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define NUM_THREADS 8 char *messages[NUM_THREADS]; void *PrintHello(void *threadid)
    {
    int *id_ptr, taskid; sleep();
    id_ptr = (int *) threadid;
    taskid = *id_ptr;
    printf("Thread %d: %s\n", taskid, messages[taskid]);
    pthread_exit(NULL);
    } int main(int argc, char *argv[])
    {
    pthread_t threads[NUM_THREADS];
    int *taskids[NUM_THREADS];
    int rc, t; messages[] = "English: Hello World!";
    messages[] = "French: Bonjour, le monde!";
    messages[] = "Spanish: Hola al mundo";
    messages[] = "Klingon: Nuq neH!";
    messages[] = "German: Guten Tag, Welt!";
    messages[] = "Russian: Zdravstvytye, mir!";
    messages[] = "Japan: Sekai e konnichiwa!";
    messages[] = "Latin: Orbis, te saluto!"; for(t=;t<NUM_THREADS;t++) {
    taskids[t] = (int *) malloc(sizeof(int));
    *taskids[t] = t;
    printf("Creating thread %d\n", t);
    rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskids[t]);
    if (rc) {
    printf("ERROR; return code from pthread_create() is %d\n", rc);
    exit(-);
    }
    } pthread_exit(NULL);
    }

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

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示例代码如下:这里是结果

     /*****************************************************************************
    * FILE: join.c
    * DESCRIPTION:
    * This example demonstrates how to "wait" for thread completions by using
    * the Pthread join routine. Threads are explicitly created in a joinable
    * state for portability reasons. Use of the pthread_exit status argument is
    * also shown. Compare to detached.c
    ******************************************************************************/
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define NUM_THREADS 4 void *BusyWork(void *t)
    {
    int i;
    long tid;
    double result=0.0;
    tid = (long)t;
    printf("Thread %ld starting...\n",tid);
    for (i=; i<; i++)
    {
    result = result + sin(i) * tan(i);
    }
    printf("Thread %ld done. Result = %e\n",tid, result);
    pthread_exit((void*) t);
    } int main (int argc, char *argv[])
    {
    pthread_t thread[NUM_THREADS];
    pthread_attr_t attr;
    int rc;
    long t;
    void *status; /* Initialize and set thread detached attribute */
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); for(t=; t<NUM_THREADS; t++) {
    printf("Main: creating thread %ld\n", t);
    rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t);
    if (rc) {
    printf("ERROR; return code from pthread_create() is %d\n", rc);
    exit(-);
    }
    } /* Free attribute and wait for the other threads */
    pthread_attr_destroy(&attr);
    for(t=; t<NUM_THREADS; t++) {
    rc = pthread_join(thread[t], &status);
    if (rc) {
    printf("ERROR; return code from pthread_join() is %d\n", rc);
    exit(-);
    }
    printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status);
    } printf("Main: program completed. Exiting.\n");
    pthread_exit(NULL);
    }

POSIX 线程编程(二)线程建立与终止的更多相关文章

  1. day31_8.12并发编程二线程

    一.进程间的通信 在进程中,可以通过Queue队列进行通信,队列有两个特点: 1.先进先出.(先来的数据先被取出) 2.管道式存取.(数据取出一次后就不会在有了) 在python中有以下方法来操作数据 ...

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

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

  3. 异步线程编程,线程池,线程组,后面涉及ThreadLocal在理解

    join模拟订单 package com.future.demo.future; /** * * * @author Administrator * */ public class NormalThr ...

  4. linux c编程:线程互斥二 线程死锁

    死锁就是不同的程序在运行时因为某种原因发生了阻塞,进而导致程序不能正常运行.阻塞程序的原因通常都是由于程序没有正确使用临界资源. 我们举个日常生活中的例子来比喻死锁.我们把马路上行驶的汽车比作运行着的 ...

  5. Python 之并发编程之线程上

    一.线程概念 进程是资源分配的最小单位 线程是计算机中调度的最小单位 多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都 ...

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

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

  7. Posix线程编程指南

    Posix线程编程指南 Posix线程编程指南... 1 一线程创建与取消... 2 线程创建... 2 1.线程与进程... 2 2. 创建线程... 2 3. 线程创建属性... 2 4. 创建的 ...

  8. Posix线程编程指南(1)

    这是一个关于Posix线程编程的专栏.作者在阐明概念的基础上,将向您详细讲述Posix线程库API.本文是第一篇将向您讲述线程的创建与取消.   一.线程创建 1.1 线程与进程相对进程而言,线程是一 ...

  9. Unix环境高级编程(十二)线程控制

    本章介绍了一个进程中多个线程之间如何保持数据的似有性及进程的系统调用如何与线程进行交互. 1.线程限制: Single Unix定义了一线线程操作的限制,和其他的限制一样,可以通过sysconf来查询 ...

随机推荐

  1. 国王的烦恼---nyoj

    国王的烦恼 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描述 C国由n个小岛组成,为了方便小岛之间联络,C国在小岛间建立了m座大桥,每座大桥连接两座小岛.两个小岛间可能存在 ...

  2. 通过top 5等待事件查看sql语句

    设计的动态性能视图有:v$session_event,v$session,v$sqlarea,首先在v$session_event中可以找到event,然后通过其动态性能视图找到sid,可以在v$se ...

  3. 【NOIP2011 Day 2】观光公交

    [问题描述] 小城Y市,拥有n个景点.由于慕名而来的游客越来越多,Y市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第0分钟出现在1号景点,随后依次前往2.3.4……n号景点.从第 ...

  4. NYOJ心急的C小加——贪心

    这个题会联想到拦截导弹的题目http://codevs.cn/problem/1044/ 首先用动态规划,利用Dilworth定理解题,然而超时了(╥╯^╰╥) 关于Dilworth定理,我的理解: ...

  5. shell学习第一弹-初识

    1.shell简介: shell是系统的用户界面,提供了用户与内核进行交互的一种接口.可以看做是用户与内核之间的一扇窗户.它接收用户输入的命令并把它送入内核执行. 常见的有bash,tcsh,csh, ...

  6. 用户 'NT Service\MSSQLServerOLAPService' 登录失败

    初学SSAS,部署微软官方示例项目AdventureWorksDW2012Multidimensional时出现错误:用户 'NT Service\MSSQLServerOLAPService' 登录 ...

  7. 06《UML大战需求分析》之六

    不知不觉中,大多数课程的学习已经接近了尾声,<UML大战需求分析>这本书也陪伴了我们很久.在学习的过程中,我发现很多课程中其实都离不开UML.足以证明,UML在需求分析中的重大作用和在我们 ...

  8. Spring中xml文档的schema约束

    最开始使用Spring框架的时候,对于其配置文件xml,只是网上得知其使用方法,而不明其意.最近想着寻根问底的探究一下.以下是本文主要内容: 1.配置文件示例.   <?xml version= ...

  9. JS 封装一个对数组去重的函数

    var zz = [1,2,3,5,5,7,8,6,6]; var se = []; d(se); function d(attr){ for(var i = 1;i<zz.length;i++ ...

  10. day28 re(正则)模块

    目录 re模块有什么用? re模块的基础使用 元字符 终极 贪婪模式 非贪婪模式 re模块高级 comple match和search re.split() sub和subn 分组 re模块有什么用? ...