创建与终止线程

线程的管理常用的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. 安卓离线SDK Windows版 资源包下载地址全集

    1.Tools    https://dl-ssl.google.com/android/repository/platform-tools_r19.0.1-windows.zip https://d ...

  2. SQL SERVER读书笔记:nolock

    让查询语句不去申请共享锁,从而消除死锁,效果立竿见影. 缺点: 1.脏读 2.只能解决共享锁(S锁)参与的问题 3.需要修改语句本身才能使用

  3. luogu2508 [HAOI2008]圆上的整点

    题目大意 给出\(r\),求圆\(x^2+y^2=r^2\)上坐标均为整数的点数.\(n<=2,000,000,000\) 总体思路 我们看到这个数据大小,还是个数学题,想到这个的时间复杂度应当 ...

  4. spark rdd median 中位数求解

    lookup(key) Return the list of values in the RDD for key key. This operation is done efficiently if ...

  5. 【POJ 3090】 Visible Lattice Points

    [题目链接] http://poj.org/problem?id=3090 [算法] 通过观察发现,在这个平面直角坐标系中,除了(1,1),(1,0)和(0,1),所有可见点的横纵坐标互质 那么,问题 ...

  6. python学习-字符串 列表 元祖

    目录 Python翻转字符串(reverse string) 简单的步长为-1, 即字符串的翻转(常用) 递归反转 借用列表,使用reverse()方法 字符串常用操作 index split 切片 ...

  7. D - Knight Tournament(set)

    Problem description Hooray! Berl II, the king of Berland is making a knight tournament. The king has ...

  8. Hadoop MapReduce编程 API入门系列之最短路径(十五)

    不多说,直接上代码. ======================================= Iteration: 1= Input path: out/shortestpath/input. ...

  9. ShowDialog函数与Form的Activated函数同时使用的陷阱

    当我们需要在form启动之时,焦点显示在特定的控件“btn”上,我们可以先将btn的TabIndex设为0,然后要确保它visible=true,最后在Form的Activated事件方法中btn.G ...

  10. C#中大批量导入数据SqlBulkCopy

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...