Linux多线程

进程和线程的区别有哪些呢?

进程是资源分配的最小单位,线程是CPU调度的最小单位 

进程有自己的独立地址空间,线程共享进程中的地址空间 

进程的创建消耗资源大,线程的创建相对较小

进程的切换开销大,线程的切换开销相对较小 

进程:程序执行的过程叫进程。

线程:进程内部的一条执行序列或执行路径,一个进程可以包含多条线程(多线程)!

每个进程最少有一个线程,例如下面代码:

#include <stdio.h>

int main()
{
    return 0;
}

        虽然只有一个主函数main,主函数的线程又叫主线程,其他的线程都叫它的子线程

下面来认识一下创建线程,退出线程,等待线程这些函数所需的参数以及具体是什么意义

线程的创建:

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

//里面有四个参数
//pthread_t *thread: 接收创建的线程的ID
//attr: 指定线程的属性   一般为NULL
//void *(start_routine)(void *): 其中start_routine指定线程函数  然后前面那个void*就是函数的返回值是void *的,后面括号里的void *就是这个函数的参数是void *类型
//arg: 给线程函数传递的参数(如果上面那个线程函数的参数是void *的话,这块填NULL就好)

线程的等待函数:

int pthread_join(pthread_t thread, void **retval); 

//pthread_join()等待thread指定的线程退出,线程未退出时,该方法阻塞 
//retval:接收thread线程退出时,指定的退出信息(这块如果没有特殊的返回信息,写NULL就好)

线程的退出函数:

int pthread_exit(void *retval); 

//retval:指定退出信息 

然后下面来写一个简单的代码来实现一下多线程:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h> //多线程的创建  等待  退出所需的头文件

void* fun(void* arg)     //线程函数
{
    for(int i = 0 ; i < 3 ; i++)
    {
        printf("fun run!\n");
    }
}

int main()
{
    pthread_t id;  //线程id
    pthread_create(&id,NULL,fun,NULL);  //线程的创建
    for(int i = 0 ; i < 3 ; i++)
    {
        printf("main run");
    }
    
}

上述程序的结果应该是main run和fun run各打印三次  但是结果不尽人意,如下图:

Linux多线程

 结果是子线程没有执行,只有主线程,这块就得提一下子线程和主线程的执行顺序----> 并发执行

下面来看一张照片:

Linux多线程

 来自于《Linux高性能服务器编程》上的一张照片,上面说了,多线程并发是看起来像“并发”,其实是cpu以时间片作为周期来切换线程来执行,也就是说,在上述代码执行的时候,是主线程在第一个时间片内先抢到了cpu资源,先执行的主线程,然后在第一个时间片内,主线程结束了,进程也就结束了,当然子线程也就不会打印了,这时候上面说到的线程等待函数就派上用场了

还有一位大哥在博客中写的很好,很清楚:

多线程(并发执行)_Bella_chene的博客-CSDN博客_多线程执行

来看下面代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h> //多线程的创建  等待  退出所需的头文件

void* fun(void* arg)     //线程函数
{
    for(int i = 0 ; i < 3 ; i++)
    {
        printf("fun run!\n");
    }
}

int main()
{
    pthread_t id;  //线程id
    pthread_create(&id,NULL,fun,NULL);  //线程的创建
    for(int i = 0 ; i < 3 ; i++)
    {
        printf("main run");
    }
    
    pthread_join(id,NULL); //id就是指定的线程id   这块的id就是子线程的线程id
                           //这块的NULL是在子线程中没有用篇thread_exit()返回的值
    
}

加上等待函数pthread_join()之后的运行结果也印证了上述时间片的那个说法:

Linux多线程

 在第一个时间片内,主函数执行完,之后本来是要结束进程的,但是pthread_join函数这块传入的是子线程的线程id,必须等子线程执行完之后,他才可以结束,要不就储于阻塞状态!

然后还有一个线程退出函数,下面来介绍一下:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h> //多线程的创建  等待  退出所需的头文件

void* fun(void* arg)     //线程函数
{
    for(int i = 0 ; i < 3 ; i++)
    {
        printf("fun run!\n");
    }
    
    pthread_exit("fun run over");//这块返回fun run over
}

int main()
{
    pthread_t id;  //线程id
    pthread_create(&id,NULL,fun,NULL);  //线程的创建
    for(int i = 0 ; i < 3 ; i++)
    {
        printf("main run");
    }
    
    char * s= NULL; //将pthread_exit返回的值存储于s中
    pthread_join(id,(void**)&s); //id就是指定的线程id   这块的id就是子线程的线程id
                                 //(void**)&s用来接收线程推出的值
    printf("%s\n",s);
}

附上运行结果:
Linux多线程

 pthread_exit()函数的返回值打印在了最后!

这样的话,基本的Linux的多线程基础基本就没了,后面会陆续更新多线程用信号量控制,用互斥锁控制!

奥里给,兄弟们!

上一篇:tlpi:线程取消(pthread_cancel...)


下一篇:thread互斥测试