Linux:线程及其控制

我们已经学了线程的创建,现在要学习线程的控制

线程等待

我们来先写一个没有线程等待的代码:

pthcon.c:

#include<stdio.h>
#include<pthread.h>
void* gopthread(void* arg){
   while(1){
    printf("pthread is running\n");
    sleep(1);
   }
}
int main(){
    pthread_t tid;
    int n=pthread_create(&tid,NULL,gopthread,(void*)"pthread 1");
    if(n!=0){
        perror("creat failed\n");
        return -1;
    }
    if(n==0){
        printf("main thread wait success\n");
    }

    return 0;
}

可以看到我们的线程每次运行的结果都是随机的,有时候主线程还没运行完,gopthraed会先运行完;就像在进程中,我们更期望的子进程先运行完,所以我们更希望mian线程后退出

所以线程等待的正确用法:

while :; do ps -aL;sleep 1;done

pthcon.c:

#include<stdio.h>
#include<pthread.h>
void* gopthread(void* arg){
    int cnt=5;
    while(cnt--){
    printf("pthread is running\n");
    sleep(1);
   }
}
int main(){
    pthread_t tid;
    int n=pthread_create(&tid,NULL,gopthread,(void*)"pthread 1");
    if(n!=0){
        perror("creat failed\n");
        return -1;
    }
    n=pthread_join(tid,NULL);
    printf("maim pthread begin\n");
    if(n==0){
        printf("main thread wait success\n");
    }

    return 0;
}
#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
// 返回:若成功返回0,否则返回错误编号

调用pthread_join函数的线程将会一直阻塞,直到我们指定调用的线程(也就是代码里的gopthread)从main中调用pthread_exit、从例程中返回或者被取消,它不停止,main就一直阻塞。如果我们的gopthread从main中返回,那么rval_ptr将包含返回码;如果线程被取消,则由rval_ptr指定的内存单元就被置为PTHREAD_CANCELED

①可以通过调用pthread_join自动把线程置于分离状态,这样资源就可以恢复。如果线程已经处于分离状态,pthread_join调用就会失败,返回EINVAL。

②如果对线程的返回值不感兴趣,可以把rval_ptr置为NULL。在这种情况下,调用pthread_join函数将等待指定的线程终止,但并不获得线程的终止状态。

例如我们调用两次该函数:

#include<stdio.h>
#include<pthread.h>
void* gopthread(void* arg){
    int cnt=5;
    while(cnt--){
    printf("pthread is running\n");
    sleep(1);
   }
}
int main(){
    pthread_t tid;
    int n=pthread_create(&tid,NULL,gopthread,(void*)"pthread 1");
    if(n!=0){
        perror("creat failed\n");
        return -1;
    }
    n=pthread_join(tid,NULL);
        n=pthread_join(tid,NULL);
        printf("n==%d\n",n);
    printf("maim pthread begin\n");
    if(n==0){
        printf("main thread wait success\n");
    }

    return 0;
}

这时候我们的线程已经处于分离状态,但又调用了一次该函数,所以会报错,3是错误码

pthread_create里第三个参数,我们在前文中提到用结构体,如何把结构体的地址传过去:

#include<stdio.h>
#include<pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
typedef struct ThreadData{
    char name[20];
    int num;
}ThreadData;//定义结构体

void* gopthread(void* arg){
    int cnt=5;
    while(cnt--){
    printf("pthread is running\n");
    sleep(1);
   }
}
int main(){
    pthread_t tid;
    ThreadData *td=(ThreadData*)malloc(sizeof(ThreadData));//防止两个线程同时访问同一片内存,破坏坏主线程的完整性及独立性
    strcpy(td->name,"thread-1");
    td->num=1;
    int n=pthread_create(&tid,NULL,gopthread,(void*)&td);//传参
    if(n!=0){
        perror("creat failed\n");
        return -1;
    }
    n=pthread_join(tid,NULL);
    printf("n==%d\n",n);
    printf("maim pthread begin\n");
    if(n==0){
        printf("main thread wait success\n");
    }
    free(td)
;    return 0;
}

集贸,这次我一定要解决你

哦原来是没链接上主机

如果我们想创建多线程呢?

#include<stdio.h>
#include<pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
void*  gopthread(void* args){
    char* name=(char*)args;
    while(1){       
        printf("%s pthread is running\n",name);
        sleep(1);
    }
    return NULL;
}


int main(){
    char names[10][128];
    pthread_t tids[10];
    for(int i=1;i<=10;i++){
        snprintf(names[i],sizeof(names[i]),"thread-%d",i);
        pthread_create(&tids[i], NULL,gopthread,names[i]);
    }
    sleep(1000);
    return 0;
}

我们发现即使我们按顺序创建线程,但是却不能按顺序调度线程

没事,退出去有顺序就好(加入线程等待)

#include<stdio.h>
#include<pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
void*  gopthread(void* args){
    char* name=(char*)args;
     
        printf("%s pthread is running\n",name);
        sleep(1);
    
    return args;
}


int main(){
    char names[10][128];
    pthread_t tids[10];
    for(int i=1;i<=10;i++){
        snprintf(names[i],sizeof(names[i]),"thread-%d",i);
        pthread_create(&tids[i], NULL,gopthread,names[i]);
    }
    for(int i=1;i<=10;i++){
        void* name=NULL;
        pthread_join(tids[i],&name);
        printf("%s quit...\n",(char*)name);
    }
    return 0;
}

我勒个数组越界

#include<stdio.h>
#include<pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
void*  gopthread(void* args){
    char* name=(char*)args;
     
        printf("%s pthread is running\n",name);
        sleep(1);
    
    return args;
}


int main(){
    char names[10][128];
    pthread_t tids[10];
    for(int i=0;i<10;i++){
        snprintf(names[i],sizeof(names[i]),"thread-%d",i);
        pthread_create(&tids[i], NULL,gopthread,names[i]);
    }
    for(int i=0;i<10;i++){
        void* name=NULL;
        pthread_join(tids[i],&name);
        printf("%s quit...\n",(char*)name);
    }
    return 0;
}

这下好了

线程终止

main函数结束,main线程结束,也就代表着进程结束了

所以我们得保证其他线程结束的时候,主线程再结束

return通常应用于一个函数的正常终止,exit可以结束整个程序,通常用来在异常情况下立即终止程序

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

rval_ptr:是一个无类型指针,与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针。

使用的时候调用这个接口就好了

线程取消

取消线程的前提:线程存在(存在才能被取消)

#include <pthread.h>
int pthread_cancel(pthread_t thread);
Compile and link with -pthread.

取消后线程的返回值是-1

线程分离

join函数是等待线程退出,那么我们可不可以让线程自己退出

答案是线程分离

#include <pthread.h>
int pthread_detach(pthread_t thread);

如果一个线程被创建出来,那么默认他是需要被join的

如果该线程被分离了,那么就不需要被join了

线程可以自己分离自己,也可以由主线程分离,只要存在就可以分离

本函数通常由想让自己脱离的线程使用,就如以下语句:

pthread_detach(pthread_self());
相关推荐
有请小发菜2 分钟前
Python 编程开发(01):Bash 命令行基本操作
开发语言·python·bash
dreamsever5 分钟前
Glide源码学习
android·java·学习·glide
武昌库里写JAVA6 分钟前
SpringBoot+SpringCloud面试题整理附答案
java·开发语言·算法·spring·log4j
Eternity-5277 分钟前
第十章JavaScript的应用
开发语言·javascript·ecmascript
呼啦啦啦啦啦啦啦啦10 分钟前
每日刷题(有效括号序列,滑动窗口最大值,最小的K个数,寻找第K大)
java·前端·javascript
手握风云-12 分钟前
数据结构(Java版)第五期:ArrayList与顺序表(下)
java·数据结构·算法
蜗牛沐雨12 分钟前
Go语言中的sync.Pool详解:高效对象复用
java·jvm·golang
不会玩技术的技术girl21 分钟前
Java爬虫与淘宝API接口:深度解析销量和商品详情数据获取
java·开发语言·爬虫
꧁༺△再临ཊ࿈ཏTSC△༻꧂27 分钟前
P1 练习卷(C++4道题)
开发语言·c++
MG_鹏鹏32 分钟前
SpringBoot实现单文件上传
java·spring boot·spring