背景介绍
进程:
以前,进程是最小的执行单位。进程是包含程序指令和相关资源的集合,每个进程和其他进程一起参与调度,竞争CPU、内存等资源。每次进程的切换,都存在着进程资源的保存和恢复动作,这称为上下文切换。
发现问题:
比如一个简单的GUI程序,为了有更好的交互性,通常一个任务执行界面交互,一个任务进行后台计算。每个任务都由一个进程来实现,那么相当的低效!因为每个进程的系统资源都是独占的,比如内存空间。每一次切换,这些独立资源都需要切换,所以,演化出了——利用分配给同一个进程的资源,尽量实现多个任务的方法,这就是线程
的概念。
同一个进程的多个线程,共享的是同一个进程的所有资源。
多线程
多线程
就是允许一个进程内有多个控制权,从而让多个函数的操作同时运行,即使是单核的CPU的计算机,也可以通过不停地切换线程指令,从而造成多线程同时运行的效果!
栈:
一个进程有其栈空间,就是执行函数的地址空间,一个栈中只有最下方的帧可被读,也就是只有该帧对应的函数被激活!所以多线程与栈密切相关,如果想实现多线程必须绕开一个栈的限制!——所以,在创建一个新的线程的时候,需要为这个线程创建新的栈,每个栈对应一个线程,当某个栈全部弹出时,这个线程完成任务。所以多线程存在多个栈,每个栈之间有空白区隔开,以备栈增长,对于多线程来说,任何一个栈的空白区域被填满都会导致栈溢出。
多线程同步
上面提了多线程的作用,优点,就是共享一个进程的内存等资源,以免去了频繁切换内存地址和指令的消耗,同时多个线程共享一个资源有时候会造成冲突!多线程的同步问题就产生了。有几种策略处理这种问题:
1、互斥锁
2、条件变量
3、读写锁
4、信号量
在后面文章中总结操作系统有关知识会着重说明其中的细节。
线程的创建与结束例子
#include<stdio.h>
#include<pthread.h>
void *say_hello(void* args)
{
// 线程的运行函数,必须 void* ,没说的表示返回通用指针
printf("hello from thread\n");
pthread_exit((void*)1);
}
int main()
{
pthread_t tid;
int iRet = pthread_create(&tid,NULL,say_hello,NULL);
// 参数依次是:创建线程的id,线程参数,调用函数名,传入的函数参数
if(iRet)
{
printf("pthread_create error: iRet=%d\n",iRet);
return iRet;
}
void *retval;
iRet=pthread_join(tid,&retval);
if(iRet)
{
printf("thread_join error : iRet = %d\n",iRet);
return iRet;
}
printf("retval = %ld\n",(long)retval);
return 0;
}
~bye