zoukankan      html  css  js  c++  java
  • 线程基础

    线程是cpu的调度单位,不拥有系统资源,和属于同一进程的其他线程共享进程的资源。

    一、线程标识

    进程id在整个系统中是唯一的,但线程id不同,只在它所属的进程环境中有效。

    进程id用pid_t数据类型来表示,是一个非负整数,线程id用pthread_t数据类型来表示,实现的时候可以用一个结构来代表pthread_t数据类型。因此必须使用函数来对两个线程id进行比较。

    #include <pthread.h>
    int pthread_equal(pthread_t tid1,pthread_t tid2);
    //返回值:若相等则返回非0值,否则返回0

    线程可以通过调用pthread_self函数获得自身的线程id

    #include <pthread.h>
    pthread_t pthread_self(void);

    二、线程创建

    调用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);

    当pthread_create成功返回(返回0)时,由tidp指向的内存单元被设置为新创建线程的线程id。attr参数用于定制各种不同的线程属性,NULL代表默认属性的线程。

    新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。

    线程创建时并不能保证哪个线程会先运行:是新创建的线程或调用线程。

    #include <stdio.h>
    #include <pthread.h>
    
    pthread_t ntid;
    
    void printids(const char *s)
    {
            pid_t pid;
            pthread_t tid;
    
            pid=getpid();
            tid=pthread_self();
            printf("%s pid %u tid %u
    ",s,(unsigned int)pid,(unsigned int)tid);
    }
    
    void *thr_fn(void *arg)
    {
            printids("new thread:");
            return ((void *)0);
    }
    
    int main(void)
    {
            int err;
            err=pthread_create(&ntid,NULL,thr_fn,NULL);
            printids("main thread:");
            sleep(1);
            exit(0);
    }

    输出:

    main thread: pid 4014 tid 3075741376
    new thread: pid 4014 tid 3075738432

    上述代码中,主线程需要休眠,如果主线程不休眠,它就可能退出,这样在新线程有机会运行之前整个进程就已经停止了。

    新线程不能安全地使用ntid,如果新线程在主线程调用pthread_create返回之前就运行了,那么新线程看到的是未经初始化的ntid内容。

    三、线程终止

    单个线程在不终止整个进程的情况下停止它的控制流:

    1)线程只是从启动例程中返回,返回值是线程的退出码

    2)线程可以被同一进程中的其他线程取消

    3)线程调用pthread_exit

    #include <pthread.h>
    void pthread_exit(void *rval_ptr)

    rval_ptr包含线程的退出状态,其他线程可以通过调用pthread_join函数访问到这个指针。

    #include <pthread.h>
    int pthread_join(pthread_t thread,void **rval_ptr)
    //返回值:若成功则返回0,否则返回错误编号
    #include <apue.h>
    #include <pthread.h>
    
    void *thr_fn1(void *arg)
    {
            printf("thread 1 returning
    ");
            return((void *)1);
    }
    
    void *thr_fn2(void *arg)
    {
            printf("thread 2 exiting
    ");
            pthread_exit((void *)2);
    }
    
    int main()
    {
            pthread_t tid1,tid2;
            void *tret;
    
            pthread_create(&tid1,NULL,thr_fn1,NULL);
            pthread_create(&tid2,NULL,thr_fn2,NULL);
    
            pthread_join(tid1,&tret);
            printf("thread 1 exit code %d
    ",(int)tret);
    
            pthread_join(tid2,&tret);
            printf("thread 2 exit code %d
    ",(int)tret);
    
            exit(0);
    }

    当一个线程通过调用pthread_exit退出或者简单地从启动例程中返回时,进程中的其他线程可以通过调用pthread_join函数获得该线程的退出状态

  • 相关阅读:
    C++Primer第5版学习笔记(三)
    C++Primer第5版学习笔记(二)
    C++Primer第5版学习笔记(一)
    A*寻路算法的探寻与改良(三)
    A*寻路算法的探寻与改良(二)
    A*寻路算法的探寻与改良(一)
    html5页面js判断是否安装app,以及判断是否在app内部打开html5页面
    结合prototype和xmlhttprequest封装ajax请求
    前端常见的性能优化和浏览器兼容性问题
    常见的HTTP状态码
  • 原文地址:https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/3822198.html
Copyright © 2011-2022 走看看