• linux 线程笔记


    线程与进程关键字对比

    创建新流 fork/pthread_create
    退出控制流 exit/pthread_exit
    获取退出状态 waitpid/pthread_join
    在退出时的清理工作 atexit/pthread_cleanup_push
    非正常退出 abort/pthread_cancel

    创建线程

    int pthread_create(线程ID返回值, 线程属性, 任务地址, 任务附加参数)
    获取线程ID: pthread_t pthread_self(void)
    判断是否同一线程: int pthread_equal(pthread_t tid1, pthread_t tid2)

    线程终止

    线程退出方式: pthread_exit; 线程正常执行完毕返回; 被同一进程中的其它线程取消
    错误退出方式: 调用exit, _exit, _Exit都会使整个进程退出
    获取返回值: pthread_join

    线程清理

    pthread_cleanup_push: 添加一个清理函数, 如果意外退出可以确保资源释放
    pthread_cleanup_pop(0): 取消清理函数, 比如主动清理完成时便可以调用pop来取消push的操作
    以下三种情况会触发push操作:

    • 调用pthread_exit退出(调用return不会触发)
    • 响应pthread_cancel请求
    • pthread_cleanup_pop(int), int参数为非零时

    线程同步

    1.互斥量
    2.读写锁
    3.条件变量

    例子

    1.创建和退出线程

    #include <stdlib.h>
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.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(){
        int err;
        pthread_t tid1,tid2;
        void *tret;
     
        err=pthread_create(&tid1,NULL,thr_fn1,NULL);
        if(err != 0){
            perror("pthread_create error");
            return -1;
        }
        err=pthread_create(&tid2,NULL,thr_fn2,NULL);
        if(err != 0){
            perror("pthread_create error");
            return -1;
        }
     
        err=pthread_join(tid1,&tret);
        if(err != 0){
            perror("pthread_join error");
            return -1;
        }
        printf("thread 1 exit code %d
    ",(int)tret);
        err=pthread_join(tid2,&tret);
        if(err != 0){
            perror("pthread_join error");
            return -1;
        }
        printf("thread 2 exit code %d
    ",(int)tret);
        return 0;
    }
    

    2.清理函数

    #include <stdlib.h>
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
     
    void cleanup(void *arg){
        printf("in cleanup : %s
    ",arg);
    }
     
    void *
    thr_fn1(void *arg){
        puts("thread start");
        pthread_cleanup_push(cleanup,"the first time");
        pthread_cleanup_push(cleanup,"the second time");
        if(1==(int)arg)
            return((void*)1);
        else if(2==(int)arg)
            pthread_exit((void*)2);
        pthread_cleanup_pop(0);
        pthread_cleanup_pop(0);
        return ((void *)0);
    }
     
    int main(){
        int err;
        pthread_t tid1;
        void *tret;
     
    //pthread_create第四个参数,
    //0时会执行pop取消清理函数, 1时以return方式退出不触发清理函数,2时以pthread_exit方式退出触发清理函数
        err=pthread_create(&tid1,NULL,thr_fn1,(void *)1);  
        if(err != 0){
            perror("pthread_create error");
            return -1;
        }
     
        err=pthread_join(tid1,&tret);
        if(err != 0){
            perror("pthread_join error");
            return -1;
        }
        printf("thread 1 exit code %d
    ",(int)tret);
        return 0;
    }
    

    3.互斥量

    #include <stdlib.h>
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <string.h>
     
    struct people{
        char name[10];
        int age;
        int count;
        pthread_mutex_t lock;
    };
     
    struct people * init(){
        struct people *man;
        if((man=malloc(sizeof(struct people))) != NULL){
            man->count=1;
            if(pthread_mutex_init(&man->lock,NULL) != 0){
                free(man);
                return NULL;
            }
            strcpy(man->name,"wahaha");
            man->age=20;
        }
        return man;
    }
     
    void add_count(struct people *man){
        pthread_mutex_lock(&man->lock);
        puts("----in add_count----");
        printf("now count=%d
    ",++man->count);
        puts("----out add_count----");
        pthread_mutex_unlock(&man->lock);
    }
     
    void del_count(struct people *man){
        pthread_mutex_lock(&man->lock);
        if(--man->count == 0){
            pthread_mutex_unlock(&man->lock);
            pthread_mutex_destroy(&man->lock);
            puts("last count to del");
            free(man);
        }else{
            pthread_mutex_unlock(&man->lock);
        }
    }
     
    void * thr_fn(void *arg){
       add_count(arg);
       sleep(1);
       del_count(arg);
    }
     
    int main(){
        struct people *man;
        man=init();
        if(man == NULL){
            perror("man init error");
            return -1;
        }
     
        int err;
        pthread_t tid1,tid2;
     
        err=pthread_create(&tid1,NULL,thr_fn,man);
        if(err != 0){
            perror("pthread_create error");
            return -1;
        }
        err=pthread_create(&tid2,NULL,thr_fn,man);
        if(err != 0){
            perror("pthread_create error");
            return -1;
        }
     
        err=pthread_join(tid1,NULL);
        if(err != 0){
            perror("pthread_join error");
            return -1;
        }
        err=pthread_join(tid2,NULL);
        if(err != 0){
            perror("pthread_join error");
            return -1;
        }
     
        del_count(man);
        return 0;
    }
    
  • 相关阅读:
    通过指定的“虚拟路径”返回路径下“文件名列表”
    ASP.NET Session丢失问题原因及解决方案
    纯CSS打造Bubble气泡提示框
    分享几个超级震憾的图片特效
    有了jQuery.Jcrop,选取美女的哪个部位你说了算
    jQueryTranslator调用Google翻译实例及源码【译】
    轻松学习正则表达式【译】
    Android系统源代码情景分析:基础知识
    HTML5斯诺克桌球俱乐部【译】
    ASP.NET中使用V3版本的Google Maps API【译】
  • 原文地址:https://www.cnblogs.com/cfans1993/p/5608848.html
Copyright © 2020-2023  润新知