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());
相关推荐
du fei6 分钟前
C# 与 相机连接
开发语言·数码相机·c#
别来无恙✲6 分钟前
SpringBoot启动方法分析
java·springboot·场景设计
独好紫罗兰6 分钟前
洛谷题单3-P2669 [NOIP 2015 普及组] 金币-python-流程图重构
开发语言·python·算法
1zero107 分钟前
[C语言笔记]09、指针
c语言·开发语言·笔记
青橘MATLAB学习12 分钟前
钢管下料问题:基于Matlab的优化求解与实践
开发语言·数学建模·matlab·钢管下料
Jay_See13 分钟前
Leetcode——239. 滑动窗口最大值
java·数据结构·算法·leetcode
褚翾澜22 分钟前
Ruby语言的代码重构
开发语言·后端·golang
DKPT22 分钟前
Eclipse,MyEclipse,IDEA,Vscode这些编译器和JDK的相爱相杀
java·eclipse·编辑器·intellij-idea·myeclipse
肠胃炎24 分钟前
真题246—矩阵计数
java·线性代数·算法·矩阵·深度优先
前行的小黑炭1 小时前
设计模式:为什么使用模板设计模式(不相同的步骤进行抽取,使用不同的子类实现)减少重复代码,让代码更好维护。
android·java·kotlin