百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>服务器> Linux多线程 创造新线程 线程的生命周期
分享文章到:

Linux多线程 创造新线程 线程的生命周期

发布时间:01/15 来源: 浏览: 关键词:
linux多线程设计是指基于Linux操作系统下的多线程设计,包括多任务程序的设计,并发程序设计,网络程序设计,数据共享等。Linux系统下的多线程遵循POSIX线程接口,称为pthread。

创造新线程

一、线程的ID

pthread_t:结构体(FreeBSD5.2、Mac OS10.3)/unsigned long int(linux)
                /usr/include/bits/pthreadtypes.h

获取线程ID:pthread_self()

一个实例:获取主线程ID


#include "apue.h"

int main()
{
    pid_t pid;
    pthread_t tid;

    pid = getpid();
    tid = pthread_self();

    printf("pid is %u, tid is %x\n", pid, tid);

    return 0;
}

思考:线程ID出了进程范围还有效吗?

二、创造新线程


int pthread_create(pthread_t *restrict tidp,
                             const pthread_attr_t *restrict attr,
                             void *(*start_routine)(void *),
                             void *restrict arg)
第一个参数:新线程的id,如果成功则新线程的id回填充到tidp指向的内存
第二个参数:线程属性(调度策略,继承性,分离性...)
第三个参数:回调函数(新线程要执行的函数)
第四个参数:回调函数的参数
返回值:成功返回0,失败则返回错误码
编译时需要连接库libpthread

实例:创建线程,打印ID

程序框图


/*AUTHOR:    WJ
 *DATE:        2015-3-18
 *
 *
 *getpid()            获取进程ID
 *pthread_self()    获取ID
 *
 *int pthread_create(pthread_t *thread,
 *                     const pthread_attr_t *attr,
 *                     void *(*start_routine) (void *),
 *                 void *arg);
 *第一个参数,新线程id,创建成功系统回填
 *第二个参数,新线程到属性,NULL为默认属性
 *第三个参数,新线程到启动函数
 *第四个参数,传递给新线程
 */
#include "apue.h"

void print_id(char *s)
{
    pid_t pid;
    pthread_t tid;

    pid = getpid();
    tid = pthread_self();

    printf("%s pid is %u, tid is 0x%x\n", s, pid, tid);

}

void *thread_fun(void *arg)
{
    print_id(arg);
    return (void *)0;
}

int main()
{
    pthread_t ntid;
    int err;

    err = pthread_create(&ntid, NULL, thread_fun, "new thread");
    if(err != 0 )
    {
        printf("create new thread failed\n");
        return 0;
    }
    
    print_id("main thread :");
    sleep(2);

    return 0;


}

线程的生命周期

一、初始线程/主线程

1、当c程序运行时,首先运行main函数。在线程代码中,这个特殊的执行流被称作初始线程或者主线程。你可以在初始线程中做任何普通线程可以做的事情。
2、主线程的特殊性在于,它在main函数返回的时候,会导致进程结束,进程内所有的线程也将会结束。这可不是一个好的现象,你可以在主线程中调用pthread_exit函数,这样进程就会等待所有线程结束时才终止。
3、主线程接受参数的方式是通过argc和argv,而普通的线程只有一个参数void*
4、在绝大多数情况下,主线程在默认堆栈上运行,这个堆栈可以增长到足够的长度。而普通线程的堆栈是受限制的,一旦溢出就会产生错误

二、线程的创建

1、主线程是随着进程的创建而创建
2、其他线程可以通过调用函数来创建,主要调用pthread_create
3、请注意,新线程可能在当前线程从函数pthread_create返回之前就已经运行了,甚至新      线程可能在当前线程从函数pthread_create返回之前就已经运行完毕了。

三、实例:主线程的特殊性

点击(此处)折叠或打开

    /*AUTHOR:    WJ
     *DATE:        2015-3-18
     *
     *
     *getpid()            获取进程ID
     *pthread_self()    获取县城ID
     *
     *int pthread_create(pthread_t *thread,
     *                     const pthread_attr_t *attr,
     *                     void *(*start_routine) (void *),
     *                 void *arg);
     *第一个参数,新线程id,创建成功系统回填
     *第二个参数,新线程到属性,NULL为默认属性
     *第三个参数,新线程到启动函数
     *第四个参数,传递给新线程

        *
        *主线程的接收的参数都放在argv[], 而参数的个数则由argc统计

     */
    #include "apue.h"

    struct student {
        int age;
        char name[20];
        char id[4];
    };

    void *thread_fun(void *stu)
    {
        sleep(1);
        printf("student age is %d, name is %s, id is %s\n",((struct student *)stu)->age, ((struct student *)stu)->name, ((struct student *)stu)->id);
        return (void *)0;
    }

    int main(int argc, char *argv[])
    {
        pthread_t tid;
        int err;
        int *rval;

        struct student stu;
        stu.age = 20;
        memcpy(stu.name, "zhangsan", 20);
        memcpy(stu.id, "007", 5);

        err = pthread_create(&tid, NULL, thread_fun, (void *)(&stu));
        if(err != 0)
        {
            printf(" create new thread failed\n");
            return 0;
        }


        int i;
        printf("main thread have %d args\n", argc);
        for(i=0; i<argc; i++)
        {
            printf("main thread args is %s\n", argv[i]);
        }

        pthread_exit(rval);
    }

四、线程的四个基本状态

1、就绪:当线程刚被创建时就处于就绪状态,或者当线程被解除阻塞以后也会处于就绪状态。就绪的线程在等待一个可用的处理器,当一个运行的线程被抢占时,它立刻又回到就绪状态
2、运行:当处理器选中一个就绪的线程执行时,它立刻变成运行状态
3、阻塞:线程会在以下情况下发生阻塞:试图加锁一个已经被锁住的互斥量,等待某个条件变量,调用singwait等待尚未发生的信号,执行无法完成的I/O信号,由于内存页错误
4、终止:线程通常启动函数中返回来终止自己,或者调用pthread_exit退出,或者取消线程


五、线程的回收

1、线程的分离属性:
分离一个正在运行的线程并不影响它,仅仅是通知当前系统该线程结束时,其所属的资源可以回收。一个没有被分离的线程在终止时会保留它的虚拟内存,包括他们的堆栈和其他系统资源,有时这种线程被称为“僵尸线程”。创建线程时默认是非分离的

2、如果线程具有分离属性,线程终止时会被立刻回收,回收将释放掉所有在线程终止时未释放的系统资源和进程资源,包括保存线程返回值的内存空间、堆栈、保存寄存器的内存空间等。

3、终止被分离的线程会释放所有的系统资源,但是你必须释放由该线程占有的程序资源。由malloc或者mmap分配的内存可以在任何时候由任何线程释放,条件变量、互斥量、信号灯可以由任何线程销毁,只要他们被解锁了或者没有线程等待。但是只有互斥量的主人才能解锁它,所以在线程终止前,你需要解锁互斥量

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有3人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板