• 线程


     堆栈

      线程包含线程ID,寄存器的值栈。

     堆属于整个进程, 栈属于线程级别的。

     一个进程可能出现多个栈,线程之间的栈是独立的,但是可以互相访问的。调度优先级,等属于线程的。

     errno属于线程的,在线程栈中

     CPU同一时间只能执行一条指令。进程内所有的信息对于线程都是共享的,包括执行代码,全局变量,和堆内存,栈以及文件描述符。

     线程标识:

        进程用pid_t表示,是一个unsigned int

        线程ID用pthread_t表示,pthread_t不能把它当整数处理。

        线程可以通过pthread_self()函数获得自身的线程ID。

    线程创建:

    -一个进程最少有一个线程,单线程方式启动。。

    在进程中只有一个控制线程,捕捉信号函数最好写在控制线程中,否则程序会别的异常复杂。

    程序开始运行的时候每个进程只有一个线程。它以当线程的方式启动。在创建多个线程以前,进程的行为,与传统的进程没有区别。

    gcc 在链接的时候需要增加-lpthread选项。-lpthread 表示链接libpthread.so库。

    创建一个线程调用pthread_create函数。

    #include <pthread.h>

    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
    void *(*start_routine) (void *), void *arg);

    第一个参数:线程id

    第二个参数:一般为NULL 线程的一些属性

    第三个参数:线程回调函数

    第四个参数:传递给线程回调函数的参数

     创建成功返回零,失败返回错误码。errno

     ps -eLF 查看线程。

    线程退出

    1. 在启动函数中返回,返回值是线程退出码

    2.线程可以在同一个进程中的线程取消。

    3.调用exit();函数

    4.调用pthread_exit函数。

    线程调用:

    线程与线程调用时异步并行随机的。

    #include <pthread.h>

    int pthread_join(pthread_t thread, void **retval);  类似wait();

    第一个参数ID号,第二个是无类型的二级指针。

     挂起当前进程,直达参数thread指定的线程终止为止。

    如果另一个线程返回不是NULL,则保持在retval地址中。

    一个线程所使用的内存资源在应用pthread_join调用之前不会被重新分配,所以对于每个线程必须调用一次pthread_join函数。

     例子:

    /////////////////////////////////////////////////////////////////////////////////

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include<unistd.h>
    #include<sys/types.h>
    #include<errno.h>
    #include<signal.h>
    #include <pthread.h>
    #include<string.h>
    #include<malloc.h>

    void* func12(void *num)
    {
    int p = *(int*)num;//得到num[]数组的值

    free(num);
    while(1)
    {
    printf("thread%d start.. " , p );
    sleep(1);
    break;
    }

    int *a ;

     a=malloc(sizeof(int));

    *a = 100;
    return a;//代表线程已经结束了。
    }

    void* func3(void *num)
    {

    while(1)
    {
    printf("thread3 start.. " );
    sleep(1);
    // break;
    }
    pthread_exit(NULL);//线程可以被同一进程中的其他线程取消掉。
    return NULL;//这一句就不会执行啦。。
    }

    void creat_thread()
    {
    pthread_t thr1 ,thr2;
    //int num[2];//这是局部变量,函数执行完成后,内存会释放掉。所以加static,或malloc
    //num[0] = 1;
    //num[1] = 2;
    int *num1,*num2;
    num1 = (int*)malloc(sizeof(int));
    num2 = (int*)malloc(sizeof(int));

    *num1 = 1;
    *num2 = 2;
    if( pthread_create(&thr1 , NULL , func12 , num1) )//返回非零表示成果,传递num[]值 同时执行func函数
    {
    printf("thread1 error :%s " , strerror(errno));

    }

    if( pthread_create(&thr2 , NULL , func12 , num2) )//传递num[]值 同时执行func函数
    {
    printf("thread2 error :%s " , strerror(errno));
    }

    int *p = NULL;
    pthread_join(thr1 , (void*)&p);//主线程挂起,等待thr1线程的结束
    pthread_join(thr2 , NULL);//主线程挂起,等待thr2线程的结束
    printf("p= %d" , *p);

     free(p);
    }

    //main函数里面的栈与线程中的栈是可以相互访问的。
    int main(void)
    {

    puts("pthread start!");
    pthread_t thr3 ,thr4,thr5,thr6 ,thr7;

    creat_thread();
    if( pthread_create(&thr3 , NULL , func3 , NULL) )//线程函数func3
    {
    printf("thread2 error :%s " , strerror(errno));
    }


    return EXIT_SUCCESS;
    }

    /////////////////////////////////////////////////////////////////////////////////////////

    线程分离

    #include <pthread.h>

    int pthread_detach(pthread_t thread);

    一旦线程成为分离线程后,就不能再使用pthread_join了

    可分离线程的使用:

    1.主线程不需要等待子线程。

    2.主线程不关心子线程的返回码

    #include <pthread.h>

    int pthread_cancel(pthread_t thread);

    另一个线程中终止另外的线程。

     //////////////////////////////////////////////////////////////////////////////

    /*
    ============================================================================
    Name : thread.c
    Author :
    Version :
    Copyright : Your copyright notice
    Description : Hello World in C, Ansi-style
    ============================================================================
    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include<unistd.h>
    #include<sys/types.h>
    #include<errno.h>
    #include<signal.h>
    #include <pthread.h>
    #include<string.h>
    #include<malloc.h>


    void* func3(void *num)
    {
    while(1)
    {
    printf("thread3 start.. " );

    }

    return NULL;//这一句就不会执行啦。。
    }

    void* func2(void *num)
    {
    pthread_t id = *(pthread_t*)num;
    sleep(5);
    printf("thread2 start.. " );
    pthread_cancel(id);
    printf("thread2 end.. " );

    return NULL;//这一句就不会执行啦。。
    }
    void* func1(void *num)
    {
    printf("thread1 start.. " );
    while(1)
    {
    sleep(1);
    printf("thread1 living.. " );

    }
    printf("thread1 end.. " );
    return NULL;//这一句就不会执行啦。。
    }


    //main函数里面的栈与线程中的栈是可以相互访问的。
    int main(void)
    {

    puts("pthread start!");
    pthread_t thr1,thr2 , thr3 ;

    if( pthread_create(&thr1 , NULL , func1 , NULL) )//线程函数func3
    {
    printf("thread1 error :%s " , strerror(errno));
    }
    if( pthread_create(&thr2 , NULL , func2 , &thr1 ) )//线程函数func3
    {
    printf("thread2 error :%s " , strerror(errno));
    }
    if( pthread_create(&thr3 , NULL , func3, NULL ) )//线程函数func3
    {
    printf("thread3 error :%s " , strerror(errno));
    }

    pthread_detach(thr3);//设置为可分离线程 使用场景:1.主线程不需要等待子线程,也不关心子线程的返回码 ,使用pthread_join(thr3 ,NULL);已经没有用了。
    pthread_join(thr1,NULL);
    pthread_join(thr2 , NULL);

    return EXIT_SUCCESS;
    }

    //////////////////////////////////////////////////////////////////////////////////

    #include <pthread.h>

    int pthread_equal(pthread_t t1, pthread_t t2);

     比较2个线程id是否相同,相同返回非零。不同返回0.。不能像进程那样直接if(pid1 == pid2)而必须使用此函数来判断线程id是否相等

    线程属性:

    pthread_creat函数第二个参数,以前调用pthread_create传入的attr参数都是空指针,而不是指向pthread_attr_t结构的指针,

    可以使用pthread_attr_t结构修改线程默认属性,并把这些属性与创建的线程联系起来。

    可以使用pthread_attr_init函数初始化pthread_attr_t结构。

    调用pthread_attr_init以后,pthread_arrt_t的结构所包含的内容就是操作系统实现支持线程所有属性的

    默认值。如果要修改其中个别属性的值,需要调用其他函数。

    #include <pthread.h>

    int   pthread_attr_init(pthread_attr_t *attr);

          pthread_attr_init初始化pthread_attr_t结构。


    int pthread_attr_destroy(pthread_attr_t *attr);

          pthread_attr_destroy函数释放attr内存空间。

     pthread_attr_t结构对于应用程序来讲是不透明的,应用程序不需要了解有关结构的内部组成。

     pthread_detach在创建线程的时候就指定线程属性为detach,而不是创建以后再去修改线程的属性。

    #include <pthread.h>

    int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

    函数pthread_attr_setdetachstate把线程属性设置为下面合法值之一

    PTHREAD_CREATE_DETACHED 设置线程为分离状态

    PTHREAD_CREATE_JOINABLE  设置线程为正常状态 默认状态


    int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);

    ///////////////////////////////////////////////////////////////////////////

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include<unistd.h>
    #include<sys/types.h>
    #include<errno.h>
    #include<signal.h>
    #include <pthread.h>
    #include<string.h>
    #include<malloc.h>

    void*fun1(void*)
    {
    while(1)
    {
    printf("1111");
    }
    }

    void *fun2(void*)
    {

    while(1)
    {
    printf("2222");
    }
    }

    //main函数里面的栈与线程中的栈是可以相互访问的。
    int main(void)
    {
    pthread_attr_t attr;
    pthread_t thr1,thr2 ;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr , PTHREAD_CREATE_DETACHED );//设置线程属性是可分离的。

    if( pthread_create(&thr1 , &attr , func1 , NULL) )//线程函数func1
    {
    printf("thread1 error :%s " , strerror(errno));
    }
    if( pthread_create(&thr2 , NULL , func2 , &thr1 ) )//线程函数func2
    {
    printf("thread2 error :%s " , strerror(errno));
    }

    pthread_attr_destory(&attr);
    pthread_join(thr1,NULL);//已经没用了。

    return EXIT_SUCCESS;
    }

    ////////////////////////////////////////////////////////////////////////////

  • 相关阅读:
    11. 优秀的基数统计算法--HyperLogLog
    10. Redis实现限流功能
    9. Redis中游标迭代器(scan)
    8. 使用Redis查询附近的人或商家
    7. Redis的管道技术
    6. Redis在内存用完时会怎么办?以及Redis如何处理已过期的数据?
    5. 详解Redis中的事务
    4. Redis的配置文件以及持久化
    2020.7.15 遇到一个bug
    A Review of Visual Tracking with Deep Learning
  • 原文地址:https://www.cnblogs.com/yuankaituo/p/4356559.html
Copyright © 2020-2023  润新知