程序代码是软件的核心载体,软件开发的主要产出是代码,但没有运行的代码是没有任何意义的
程序运行的原理
一般书写的代码是文本格式的代码,不能直接运行,需要被编译器编译成存储在文件系统中可以被操作系统运行的可执行代码。程序完成计算任务需要把程序加载到内存中,并在操作系统的管理调度下由CPU执行。
进程包括可执行代码、内存堆空间、栈空间、供操作系统管理的数据结构。
程序执行过程
(1)操作系统将可执行代码加载到内存中,并生成相应的数据结构和内存空间;
(2)从可执行代码的起始位置读取指令并交给CPU顺序执行。若遇到跳转指令时,需要跳转到相应位置执行;
(3)程序运行时需要创建数组等数据结构时,会在无序的堆空间申请相应的内存空间,把此内存首地址记录到进程栈中。分配到内存地址记录在栈中
(4)栈由操作系统维护,主要用来记录函数内部的局部变量、堆空间分配的内存地址等
(5)每次函数调用,操作系统都会创建一个栈帧。
同时处理多个任务
主要依靠操作系统CPU的分时共享技术。若多个进程在执行,操作系统会将CPU的执行时间分成多分,进程按照某种策略轮流执行。
进程的生命周期
- 运行:当一个进程在CPU上运行时,则该进程处于运行状态。处于运行状态的进程数小于等于CPU数目;
- 就绪:当一个进程获得了除了CPU以外的一切所需资源,只要得到CPU即可运行,也称等待运行状态;
- 堵塞:当一个进程在等待某一事件发生(等待I/O完成,等待锁)而暂时提供乃至运行,即使吧CPU分配给进程也无法运行,也称等待或睡眠状态;
每次切换CPU,代价非常大。实际上,每个用户请求对应的是线程。线程为轻量级进程,在进程内创建线程,拥有自己的线程栈。线程同样有三种状态。
系统变慢和崩溃的原因
从逻辑上看,每个线程都有自己的线程栈,所有的线程栈是完全隔离的,每个方法的参数和局部变量都是隔离的,一个线程无法访问其他线程的栈内数据。但当某些代码修改内存堆里的数据,如果多个线程同时执行,可能出现同时修改数据的情况。多个线程访问共享资源的代码称为临界区,解决线程安全问题主要使用锁。
锁会引起线程阻塞,若线程数量多,就会出现线程排队等待锁的情况,线程无法并行执行,系统响应速度会变慢。被阻塞的先策划给你越来越多,占据的系统资源也越多,这些被阻塞的线程既不能继续执行,也不能释放当前已经占据的资源,在系统中一边等待一边消耗资源,如果阻塞的线程数超过了某个系统资源的极限,就会导致系统宕机,应用崩溃。
解决方法
(1)分布式系统结构
(2)限流
(3)服务降级