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

本文介绍了Linux系统中多线程编程的基础知识,包括进程与线程的概念、线程的优点,以及线程与进程的区别。重点讲解了与线程创建、退出和等待相关的API:pthread_create()、pthread_exit()和pthread_join(),并提供了代码实战示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、什么是进程:

二、什么是线程:

三、使用线程的理由:

四、线程和进程的区别:

五、与线程自身相关的API

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

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

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


一、什么是进程:

进程是程序执行时的一个实例,是担当分配系统资源(CPU时间、内存等)的基本单位,还是线程的容器

二、什么是线程:

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

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

(1)进程有独立的地址空间,线程没有单独的地址空间(同一进程内的线程共享进程的地址空间)。

(2)和进程相比,它是一种非常"节俭"的多任务操作方式,运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间

(3)线程间方便的通信机制,一个线程的数据可以直接为其它线程所用。

四、线程和进程的区别:

第一种方法:

一个进程在运行的时候,要给他分配内存,要维护它的数据段和代码段以及堆栈等等,而线程是跟进程共享这些东西,开辟多个线程不会分配新的内存,和进程相比,它是一种非常"节俭"的多任务操作方式。

第二种方法:

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;
}

执行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值