嵌入式--软件--应用程序--C语言--进程--学习笔记(高级篇--线程篇)

0-- 系列文章目录

1.进程篇:  (进程篇链接(本文章)多线程通信篇

2.网络篇:  (文章链接)

3.数组篇:  (文章链接)

4.指针篇:  (文章链接)

5.内核篇:  (文章链接)

6.硬件篇:  (文章链接)(视频链接)

...........

 1--当前文章目录

  • 前言
  • 一、理论部分
  • 二、实际操作
    • 1.创建线程(pthread_create)
    • 2.线程间参数的传递(重难点
    • 3.线程回收(pthread_join,多线程会有点小问题)
    • 4.线程的分离(pthread_detach)
    • 5.线程的取消(pthread_cancel,pthread_testcancel,pthread_setcancelstate)
    • 6.线程的清理(pthread_cleanup_push)
    • 7.互斥锁(pthread_rwlock_unlock,pthread_rwlock_wrlock,,pthread_mutex_lock)
    • 8.死锁(两把以上会)
  • 总结

一.理论部分

线程

进程在切换时系统开销大
很多操作系统引入了轻量级进程LWP
同一进程中的线程共享相同地址空间
Linux不区分进程、线程

特点

通常线程指的是共享相同地址(空间的多个任务)
使用多线程的好处( 大大提高了任务切换的效率 避免了额外的TLB & cache的刷新)

线程(共享)资源

        •可执行的指令,静态数据,进程中打开的文件描述符,

        •当前工作目录,用户ID,用户组ID

线程(私有)资源

线程ID (TID),      PC(程序计数器)和相关寄存器
堆栈,错误号 (errno),  优先级         执行状态和属性

 Linux线程库

•pthread线程库中提供了如下基本操作
        Ø 创建线程
        Ø 回收线程
        Ø 结束线程
•  同步和互斥机制
        Ø 信号量
        Ø 互斥锁

二.实际操作

1.创建线程

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

int *testThread(char *arg){
    printf("zhe shi zi xian cheng,pid=%d,tid=%lu\n",getpid(),pthread_self());
    return 0;
}

int main(){

    pthread_t tid;
    int ret;

    ret = pthread_create(&tid,NULL,(void *)testThread,NULL);
    printf("zhe shi zhu xian cheng\n");
    sleep(1);
}

 获取线程ID:两种方法

        1.。。pthread_create()其中的第一个参数

        2.。。在线程里面调用 pthread_self 函数

2.线程间参数的传递(重难点)

两种方式:选择使用(有报警,但是程序是可以的)

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

int *testThread(void *arg){
    printf("zhe shi zi xian cheng,pid=%d,tid=%lu\n",getpid(),pthread_self());
    printf("shu ru wei: %d\n", *(int *)arg);    // chuan can shu 

    pthread_exit(NULL);
    printf("after pthread exit\n");
   
}

int main(){

    pthread_t tid;
    int ret;
    int arg=5;
    int i;

        ret = pthread_create(&tid,NULL,testThread,(void*)&arg);
        printf("zhe shi zhu xian cheng,tid=%lu\n",tid);
        sleep(1);
}


/*
void *testThread(void *arg){
    printf("This is a thread test,pid=%d,tid=%lu\n",getpid(),pthread_self());
   // return NULL;
    printf("input arg=%d\n",(int)arg);
    pthread_exit(NULL);
    printf("after pthread exit\n");
}

int main(){
    pthread_t tid;
    int ret;
    int arg = 5;
   
    ret = pthread_create(&tid,NULL,testThread,(void *)arg);

    printf("This is main thread,tid=%lu\n",tid);    
    sleep(1);
}

*/

 进阶版:多线程

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void *testThread(void *arg){
    printf("This is a thread test,pid=%d,tid=%lu\n",getpid(),pthread_self());
   // return NULL;
    printf("This is %d thread.\n", (int)arg);
   // pthread_exit(NULL);
    while(1){
        sleep(1);
    }
    printf("after pthread exit\n");
}

int main(){
    pthread_t tid[5];
    int ret;
    int arg = 5;
    int i;
    for(i=0;i<5;i++){   
        ret = pthread_create(&tid[i],NULL,testThread,(void *)i);
     
//        sleep(1);   
        printf("This is main thread,tid=%lu\n",tid[i]);    
    }
    while(1){
        sleep(1);
    }
}

3.线程的回收(pthread_join,多线程会有点小问题)

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *func(void *arg){
    printf("This is child thread\n");
    sleep(25);
    pthread_exit("thread return");

}


int main(){
    pthread_t tid[100];
    void *retv;
    int i;
    for(i=0;i<100;i++){
        pthread_create(&tid[i],NULL,func,NULL);
    }
    for(i=0;i<100;i++){
       // pthread_join(tid[i],&retv);
       // printf("thread ret=%s\n",(char*)retv);
    }
    while(1){    
        sleep(1);
    } 

}

4.线程的分离(pthread_detach)

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *func(void *arg){
    printf("This is child thread\n");
    sleep(25);
    pthread_exit("thread return");

}


int main(){
    pthread_t tid[100];
    void *retv;
    int i;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

    for(i=0;i<100;i++){
        pthread_create(&tid[i],&attr,func,NULL);
       // pthread_detach(tid);
    }
    
    while(1){    
        sleep(1);
    } 

}

 用top查看,运行100个实时的内存变化

 (5)线程的取消与互斥(pthread_cancel,pthread_testcancel,pthread_setcancelstate)

取消的条件:需要取消点(sleep),,或者手动添加取消点(pthread_testcancel)

取消点的选择:(pthread_setcancelstate)哪里,不能取消,哪里可以取消

创建完成后,执行线程需要时间,

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>


void *func(void *arg){
    printf("This is child thread\n");
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);    
//    while(1)
    {
        sleep(5);
        pthread_testcancel();
    }
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
    while(1){
        sleep(1);
    }


    pthread_exit("thread return");
}


int main(){
    pthread_t tid;
    void *retv;
    int i;
    pthread_create(&tid,NULL,func,NULL);
    sleep(1);
    pthread_cancel(tid);
    pthread_join(tid,&retv);
//    printf("thread ret=%s\n",(char*)retv);
    while(1){    
        sleep(1);
    } 

}

(6)线程的清理(pthread_cleanup_push)

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void cleanup(void *arg){
    printf("cleanup,arg=%s\n",(char*)arg);

}
void cleanup2(void* arg){

    printf("cleanup2,arg=%s\n",(char*)arg);
}

void *func(void *arg){
    printf("This is child thread\n");
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
    pthread_cleanup_push(cleanup,"abcd");
    pthread_cleanup_push(cleanup2,"efgh");
    //while(1)
    {
        sleep(1);
        
    }
//    pthread_cancel(pthread_self());
    //printf("Should not print\n");
    return "1234";

    while(1){
        printf("sleep\n");
        sleep(1);
    }
    pthread_exit("thread return");
    pthread_cleanup_pop(1);
    pthread_cleanup_pop(1);
    sleep(10);
    pthread_exit("thread return");
}


int main(){
    pthread_t tid;
    void *retv;
    int i;
    pthread_create(&tid,NULL,func,NULL);
    sleep(1);
//    pthread_cancel(tid);
    pthread_join(tid,&retv);
    printf("thread ret=%s\n",(char*)retv);
    while(1){    
        sleep(1);
    } 

}

(7)互斥锁(两个线程,写同一个文件的时候,排队,先后)

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


FILE *fp;
void *func2(void *arg){
    pthread_detach(pthread_self());
    printf("This func2 thread\n");
    
    char str[]="I write func2 line\n";
    char c;
    int i=0;
    while(1){
        pthread_mutex_lock(&mutex);
        while(i<strlen(str))
        {
            c = str[i];
            fputc(c,fp);
            usleep(1);
            i++;
        }
        pthread_mutex_unlock(&mutex);
        i=0;
        usleep(1);

    }

    pthread_exit("func2 exit");

}

void *func(void *arg){
    pthread_detach(pthread_self());
    printf("This is func1 thread\n");
    char str[]="You read func1 thread\n";
    char c;
    int i=0;
    while(1){
        pthread_mutex_lock(&mutex);
        while(i<strlen(str))
        {
            c = str[i];
            fputc(c,fp);
            i++;
            usleep(1);
        }
        pthread_mutex_unlock(&mutex);
        i=0;
        usleep(1);

    }
    pthread_exit("func1 exit");
}


int main(){
    pthread_t tid,tid2;
    void *retv;
    int i;
    fp = fopen("1.txt","a+");
    if(fp==NULL){
        perror("fopen");
        return 0;
    }


    pthread_create(&tid,NULL,func,NULL);
    pthread_create(&tid2,NULL,func2,NULL);
    while(1){    
        sleep(1);
    } 

}

读取的锁,可以多个读取,写的时候阻塞

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>


pthread_rwlock_t rwlock;

FILE *fp;
void * read_func(void *arg){
    pthread_detach(pthread_self());
    printf("read thread\n");
    char buf[32]={0};
    while(1){
        //rewind(fp);
        pthread_rwlock_rdlock(&rwlock);
        while(fgets(buf,32,fp)!=NULL){
            printf("%d,rd=%s\n",(int)arg,buf);
            usleep(1000);
        }
        pthread_rwlock_unlock(&rwlock);
        sleep(1);
    }

}



void *func2(void *arg){
    pthread_detach(pthread_self());
    printf("This func2 thread\n");
    
    char str[]="I write func2 line\n";
    char c;
    int i=0;
    while(1){
        pthread_rwlock_wrlock(&rwlock);
        while(i<strlen(str))
        {
            c = str[i];
            fputc(c,fp);
            usleep(1);
            i++;
        }
        pthread_rwlock_unlock(&rwlock);
        i=0;
        usleep(1);

    }

    pthread_exit("func2 exit");

}

void *func(void *arg){
    pthread_detach(pthread_self());
    printf("This is func1 thread\n");
    char str[]="You read func1 thread\n";
    char c;
    int i=0;
    while(1){
        pthread_rwlock_wrlock(&rwlock);
        while(i<strlen(str))
        {
            c = str[i];
            fputc(c,fp);
            i++;
            usleep(1);
        }
        pthread_rwlock_unlock(&rwlock);
        i=0;
        usleep(1);

    }
    pthread_exit("func1 exit");
}


int main(){
    pthread_t tid1,tid2,tid3,tid4;
    void *retv;
    int i;
    fp = fopen("1.txt","a+");
    if(fp==NULL){
        perror("fopen");
        return 0;
    }
    pthread_rwlock_init(&rwlock,NULL);
    pthread_create(&tid1,NULL,read_func,1);
    pthread_create(&tid2,NULL,read_func,2);
    pthread_create(&tid3,NULL,func,NULL);
    pthread_create(&tid4,NULL,func2,NULL);
    while(1){    
        sleep(1);
    } 

}

(8)死锁

概念:

避免方法:

  1. 锁越少越好,最好使用一把锁
  2. 调整好锁的顺序
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;

FILE *fp;
void *func2(void *arg){
    pthread_detach(pthread_self());
    printf("This func2 thread\n");
    
    char str[]="I write func2 line\n";
    char c;
    int i=0;
    while(1){
        pthread_mutex_lock(&mutex);
        printf("%d,I got lock2\n",(int)arg);
        sleep(1);
        pthread_mutex_lock(&mutex2);
        printf("%d,I got 2 locks\n",(int)arg);

        pthread_mutex_unlock(&mutex2);
        pthread_mutex_unlock(&mutex1);
        sleep(10);

    }

    pthread_exit("func2 exit");

}

void *func(void *arg){
    pthread_detach(pthread_self());
    printf("This is func1 thread\n");
    char str[]="You read func1 thread\n";
    char c;
    int i=0;
    while(1){
        pthread_mutex_lock(&mutex);
        printf("%d,I got lock1\n",(int)arg);
        sleep(1);
        pthread_mutex_lock(&mutex2);
        printf("%d,I got 2 locks\n",(int)arg);

        pthread_mutex_unlock(&mutex2);
        pthread_mutex_unlock(&mutex);
        sleep(10);

    }
    pthread_exit("func1 exit");
}


int main(){
    pthread_t tid,tid2;
    void *retv;
    int i;
    fp = fopen("1.txt","a+");
    if(fp==NULL){
        perror("fopen");
        return 0;
    }


    pthread_create(&tid,NULL,func,1);
    pthread_create(&tid2,NULL,func2,2);

    while(1){    
        sleep(1);
    } 

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值