Linux下c语言进程和线程简单概括

12 篇文章 0 订阅
6 篇文章 0 订阅

进程VS线程

1、进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位)

2、进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。
而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。

3、线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。

4、但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。

总而言之,
进程占用资源更多,但是更安全健壮
线程占用资源少,但是相对危险,且通信方便

进程的创建、使用即通信

进程的创建和使用

进程的创建和使用

进程之间的通信(IPC)

使用fork创建的父子进程其实有点类似于直接在命令行运行两个可执行文件,他们是不能通过变量直接进行通信的需要借助集中linux中附带进程间通信工具

这里内容过多,就转载一篇大佬博主的博文吧
进程间的五种通信方式介绍

线程的创建、使用即通信

更详细的内容可以点击这里

创建线程

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
//pthread_t *thread:需要一个句柄,在此函数前定义也给pthread_t t1就好了
//const pthread_attr_t *attr:用于设定一些参数,如果是NULL的话就用默认的参数
//void *(*start_routine) (void *):函数指针,创建线程后会直接进入这个函数执行
//void *arg:线程传参传给函数指针中的void *形参,在函数中经过强制转换后就可以使用了

pthread_t pthread_self(void);
//返回pthread_creat里面的第一个参数,线程的识别码

例子

#include<stdio.h>
#include<pthread.h>

void *func1(void *arg){//这里的arg就是pthread_create中传进来的第四个参数,如果要传入的参数很多就用结构体,创建一个结构体,并赋值好各个参数,然后将其作为参数传入到线程中
	
	static char* ret = "t1 is run out";

	printf("son : %ld\n",(unsigned long)pthread_self());
	printf("param is %d\n",*((int *)arg));

	pthread_exit((void *)ret); //as return
}

int main(){
//	 int pthread_create(pthread_t * thread,const pthread_attr_t * attr,void * (*start_routine)(void *), void *arg);

	int ret;
	pthread_t t1;
	int param = 100;
	char *pret;
	ret = pthread_create(&t1,NULL,func1,(void *)&param);
	if(ret == 0){
		printf("create t1 success\n");
		printf("main : %ld\n",(unsigned long)pthread_self());
	}

//	int pthread_join(pthread_t th, void **thread_return);
	pthread_join(t1,(void**)&pret);
	printf("main : %s\n",pret);
	return 0;
}

线程互斥锁以及线程的同步

互斥锁的基本概念就是,设定一个空间,里面放置了1把锁,
当一个线程运行到这里就取走一个锁,运行完了回来就放回一个锁,没有取到锁的线程就在这里阻塞

其中需要用到以下的函数

#include <pthread.h>

//创建锁,使用默认设置的时候attr用NULL
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
//销毁锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
//加锁,加不上去就阻塞
int pthread_mutex_lock(pthread_mutex_t *mutex);
//尝试加锁,失败返回EBUSY,而不阻塞
int pthread_mutex_trylock(pthread_mutex_t *mutex);
//减锁,减不了也阻塞
int pthread_mutex_unlock(pthread_mutex_t *mutex);
// 返回:若成功返回0,否则返回错误编号

以下先创建的t1线程获取了锁,所以必定是先t1再t2

#include<stdio.h>
#include<pthread.h>
int g_data = 0;

pthread_mutex_t mutex;

void *func1(void *arg){
	//	加锁
	pthread_mutex_lock(&mutex);
	printf("t1 : %ld\n",(unsigned long)pthread_self());
	//	减锁
	pthread_mutex_unlock(&mutex);
}
void *func2(void *arg){
	//	加锁
	pthread_mutex_lock(&mutex);
	printf("t2 : %ld\n",(unsigned long)pthread_self());
	//	减锁
	pthread_mutex_unlock(&mutex);
}

int main(){
	int ret;
	char *pret;
	pthread_t t1;
	pthread_t t2;
//	创造锁
	pthread_mutex_init(&mutex,NULL);

	ret = pthread_create(&t1,NULL,func1,NULL);
	ret = pthread_create(&t2,NULL,func2,NULL);
	
//	等待两个线程退出
//	int pthread_join(pthread_t th, void **thread_return);
	pthread_join(t1,NULL);
	pthread_join(t2,NULL);

//	销毁锁
	pthread_mutex_destroy(&mutex);
	return 0;
}

线程条件

线程的条件跟锁是要一起运用的,不能没有锁只有条件
下面将会用到以下几个函数

#include <pthread.h>

//创建条件
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
//销毁条件
int pthread_cond_destroy(pthread_cond_t *cond);
//等待条件
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
//pthread_cond_wait等待条件变为真。如果在给定的时间内条件不能满足,那么会生成一个代表一个出错码的返回变量。
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);
//pthread_cond_signal函数将唤醒等待该条件的某个线程
int pthread_cond_signal(pthread_cond_t *cond);
//pthread_cond_broadcast函数将唤醒等待该条件的所有进程。
int pthread_cond_broadcast(pthread_cond_t *cond);

例子

#include<stdio.h>
#include<pthread.h>
int g_data = 0;

pthread_mutex_t mutex;
pthread_cond_t cond;
void *func1(void *arg){
	while(1){
		pthread_cond_wait(&cond,&mutex);//等待条件触发
		if(g_data == 3){
			printf("t1 : g_data = 3\n");
			printf("t1 : run\n");
			g_data = 0;
			exit(0);
		}
		sleep(1);
	}
}
void *func2(void *arg){
	while(1){
		pthread_mutex_lock(&mutex);
		printf("t2 : %d\n",g_data++);
		if(g_data == 3){
			pthread_cond_signal(&cond);   //触发并发出信息给单个pthread_cond_wait
//			pthread_cond_broadcast(&cond);//触发并发出信息给所有pthread_cond_wait
		}
		pthread_mutex_unlock(&mutex);
		sleep(1);
	}
}

int main(){
	int ret;
	int param = 100;
	char *pret;
	pthread_t t1;
	pthread_t t2;

//	init lock
	pthread_mutex_init(&mutex,NULL);
	
//	init cond
	pthread_cond_init(&cond,NULL);

//	create pthread t1 & t2
	ret = pthread_create(&t1,NULL,func1,(void *)&param);
	ret = pthread_create(&t2,NULL,func2,(void *)&param);

//	int pthread_join(pthread_t th, void **thread_return);
	pthread_join(t1,NULL);
	pthread_join(t2,NULL);

//	destroy cond
	pthread_cond_destroy(&cond);

//	destroy lock
	pthread_mutex_destroy(&mutex);
	
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值