Linux基础之多线程编程(一)

一、进程与线程

  • 什么是进程

1. 指在运行中的程序,例如使用微信就启动一个进程,操作系统就会为 该进程分配内存空间;
2. 进程是程序的一次执行的过程,或者是正在运行的一个程序;是动态过程,有它自身的产生、存在和消亡的过程
3. 进程是程序执行时的一个实例,是担当分配系统资源(CPU时间、内存等)的基本单位,还是线程的容器过程。
  • 什么是线程

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

1. 线程由进程创建的,是进程的一个实体;
2. 一个进程可以拥有多个线程;
3 .单线程:同一时刻,只允许执行一个线程;
4. 多线程:同一时刻,可以执行多个线程。

  • 并发和并行

并发:
同一时刻,多个任务交替执行;单核CPU实现的多任务就是并发
并行:
同一个时刻,多个任务同时执行,多核CPU可以实现并行

二、使用线程的理由(线程的优点):

(1) 进程有独立的地址空间,线程没有单独的地址空间(同一进程内的线程共享进程的地址空间)。
(2) 和进程相比,它是一种非常"节俭"的多任务操作方式,运行于一个进程中的多个线程,它们彼此 之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程 所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间
(3) 线程间方便的通信机制,一个线程的数据可以直接为其它线程所用。
(4) 创建 一个新线程的代价要比创建一个新进程小得多
(5) 与进程之间的切换相比,线程之间的 切换 需要OS的工作量更少
(6) 线程占用的 资源 比进程少得多

三、线程和进程的区别:

第一种方法:
一个进程在运行的时候,要给他分配内存,要维护它的数据段和代码段以及堆栈等等,而线程是跟进程共享这些东西,开辟多个线程不会分配新的内存,和进程相比,它是一种非常"节俭"的多任务操作方式。
第二种方法:
1 .根本区别:进程是操作系统进行资源分配的最小单元,线程是操作系统进行运算调度的最小单元。
2 .从属关系不同:进程中包含了线程,线程属于进程。
3. 开销不同:进程的创建、销毁和切换的开销都远大于线程。
4 .拥有资源不同:每个进程有自己的内存和资源,一个进程中的线程会共享这些内存和资源。
5 .控制和影响能力不同:子进程无法影响父进程,而子线程可以影响父线程,如果主线程发生异常会影响其所在进程和子线程。
6 .CPU利用率不同:进程的CPU利用率较低,因为上下文切换开销较大,而线程的CPU的利用率较高,上下文的切换速度快。
7. 操纵者不同:进程的操纵者一般是操作系统,线程的操纵者一般是编程人员。

四、与线程自身相关的API

  • (1)pthread_create()函数:线程创建

#include <pthread.h>
 
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
 
 
pthread_t *thread:                 pthread是一个指针参数,传出线程ID
const pthread_attr_t *attr:        用于指定线程属性,传入NULL表示使用默认属性
void *(*start_routine) (void *):   是个函数指针,是线程的主控函数
void *arg:                         是第三个函数的参数,要强制转换成泛型(void*)然后进行值 
                                    传递即可,不能传递地址
 
返回值:若成功返回0,否则返回错误编号
  • 注意:创建线程之后,有可能创建它的进程先退出了,那么;进程的存储空间将被回收,线程也就无法执行了。

  • (2)pthread_exit()函数:线程退出

#include <pthread.h>
void pthread_exit(void *retval);
 
void *retval:    retval表示线程的退出值,我们必须将该参数强转为泛型void*

  • (3)pthread_join()函数:线程等待

#include <pthread.h>
 
int pthread_join(pthread_t thread, void **retval);
 
pthread_t thread:  thread是我们要等待退出的线程的线程ID
void **retval:     retval是传出参数,用于获取线程的退出值,即,pthread_exit里的那个参数
 
在使用该函数时要注意retval参数:
 
(1) 一定要用void**强制转换为泛型指针
 
(2)该函数是将pthread_exit里的退出值 复制到 retval所指向的位置。
 
(3)该参数可以置为NULL,表示不需要获取线程退出值。

创建一个线程代码实战:

#include <stdio.h>
#include <pthread.h>
 
void *func1(void *arg){
 
        static int ret = 10;       //一定要加static,不加的话,线程的返回值将不知道会返回什么
        printf("t1:%ld thread is create\n",(unsigned long)pthread_self());  //打印线程ID号
        printf("t1:param is %d\n",*((int *)arg));            //取param参数的值
        pthread_exit((void *)&ret);                          //线程退出
}
int main(){
 
        int ret;
        int param = 100;
        pthread_t t1;
        int *pret;
 
        ret = pthread_create(&t1,NULL,func1,(void *)&param); //创建一个线程
        if(ret == 0){
                printf("main:pthread_create success\n");
        }
        printf("mian:%ld\n",(unsigned long)pthread_self());
        pthread_join(t1,(void **)&pret);           //线程等待,等待线程退出的返回值传给pret
        printf("main: t1 quit:%d\n",*pret);
        return 0;
}

执行结果:

线程共享内存空间的代码验证

#include <stdio.h>
#include <pthread.h>
 
int g_data = 0;
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
 
void *func1(void *arg){
    
    static int ret = 10;
 
    printf("t1:%ld thread is create\n",(unsigned long)pthread_self());
    printf("t1:param is %d\n",*((int *)arg));
    while(1){
        printf("t1:%d\n",g_data++);
        sleep(1);
    }
    pthread_exit((void *)&ret);
}
 
void *func2(void *arg){
 
        static int ret = 10;
 
        printf("t2:%ld thread is create\n",(unsigned long)pthread_self());
        printf("t2:param is %d\n",*((int *)arg));
    while(1){
                printf("t1:%d\n",g_data++);
                sleep(1);
        }
 
        pthread_exit((void *)&ret);
}
 
 
int main(){
    
    int ret;
    int param = 100;
    pthread_t t1;
    pthread_t t2;
 
    int *pret;
 
    ret = pthread_create(&t1,NULL,func1,(void *)&param);
    if(ret == 0){
        printf("main:pthread_create success\n");
    }
 
    ret = pthread_create(&t2,NULL,func1,(void *)&param);
        if(ret == 0){
                printf("main:pthread_create success\n");
        }
 
    printf("mian:%ld\n",(unsigned long)pthread_self());
    while(1){
 
                printf("main:%d\n",g_data++);
                sleep(1);
        }
 
    pthread_join(t1,(void **)&pret);
    pthread_join(t2,(void **)&pret);
 
    printf("main: t1 quit:%d\n",*pret);
    printf("main: t2 quit:%d\n",*pret);
    return 0;
}

执行结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值