面试知识点汇总

一、进程和线程

  1. 进程定义

进程是进程实体的运行过程,是计算机系统进行资源分配处理机调度的基本单位,进程实体包括三部分,分别是程序段、相关数据、PCB。

能够独立地拥有资源、独立调度和分配,这两个特性使得进程成为能够独立运行的独立单位,也构成了进程并发的基础。

  1. 由进程引入线程

进程包含的问题

引入进程的目的是使得多个程序能够并发执行,来提高系统资源的利用率和吞吐量;而引入线程的目的是减少程序在并发执行时所付出的时空开销。

进程的引入,使得计算机程序能够并发执行,大大提高了计算机的吞吐量。

但是进程在创建时,必须分配进程除处理机之外的所有资源(内存空间、I/O设备等),也需要建立对应的PCB;进程在撤销时,也需要回收这些资源;在执行进程之间的切换时,也需要保留当前进程的CPU环境,并设置新进程的CPU环境。这些操作都需要花费处理机时间,时空开销很大,带来的结果就是限制了系统进程的数量,进程切换也不宜频繁。

如何解决上述问题?

站在巨人的肩膀上来看,OS设计者将 资源分配处理机调度 这两大属性分开,由OS分开处理,在接受作为资源分配的基本单位的同时,并不作为处理机调度的基本单位。这样就避免了进程作为调度的基本单位带来的时空开销大的问题。

随着多处理机处理系统的出现,我们的电脑中可以有多个CPU协调运行,可并行处理多个作业,基于这样的硬件条件,传统的进程设计方法很难充分发挥多处理机的优势,原因是进程的创建、撤销、切换在多处理机条件下反而需要额外花费更大的时间空间开销,因此引入了线程的概念。

在引入线程的OS中,线程是处理机调度的基本单位,而进程仍然是资源分配的基本单位,这样使得线程成为了独立运行的基本单位,线程之间的切换仅需保留和设置少量的寄存器内容,其实就相当于是轻量级的进程,不同的是线程大大减小了进程创建撤销切换等操作带来的时空开销。

  1. 进程与线程的区别比较

  1. 调度的基本单位

线程是处理机调度的基本单位,并且线程切换的开销远小于进程切换的时空开销;进程是资源分配的基本单位

我感觉 可以理解为线程是将原来的进程“缩小并集合化”(缩小为线程,集合到一个进程中,该进程中的线程可以共享该进程内的各种资源,比如内存空间、数据等)

  1. 并发性(提升)

相对于进程来说,线程的并发性大大提升。引入线程的OS中,不同进程可以并发执行,一个进程之间的线程也可以并发执行,当然不同进程中的线程也可以并发执行。在多处理机系统中,一个进程中的多个线程可分配到多个处理机上,从而实现并行执行

并发:两个或多个事件在同一时间间隔内发生(微观上是分时交替运行);并行:两个或多个事件在同一时刻发生(微观上也是同时运行)

  1. 独立性(提升)

线程的独立性相对于进程而言肯定是提升很多的

  1. 系统开销(下降)

线程切换的系统开销要比进程切换的系统开销小得多,这也是引入线程的最主要原因。


写这么繁琐详细,为的是理解Java、C++开发中经常写的的多线程编程的起始原因,更好理解多线程并发编程。我们写代码的就是进程实体中的程序段。

二、JavaScript

  1. 闭包

在函数体内又定义了函数,内部函数可以引用外部函数的参数和局部变量,外部函数的返回值为内部函数,并且相关参数和变量都保存在返回的函数中。这就成为闭包。

闭包的主要功能:

在面向对象的程序设计语言里,比如Java和C++,要在对象内部封装一个私有变量,可以用private修饰一个成员变量。

在没有class机制,只有函数的语言里,借助闭包,同样可以封装一个私有变量。

function lazy_sum(arr) {
    var sum = function () {
        return arr.reduce(function (x, y) {
            return x + y;
        });
    }
    return sum;//返回的是函数名
}

var f = lazy_sum([1, 2, 3, 4, 5]); // function sum()
f(); // 15,调用函数f时才计算求和的结果,这样可以动态增长输入的array,在需要时才求和

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。因为在闭包中的函数并不会立即执行,引用时才执行,而此时循环体变量已经是一个固定的值,并不是按照循环次数变化。举例:

function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push(function () {
            return i * i;
        });
    }
    return arr;
}

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];

f1(); // 16
f2(); // 16
f3(); // 16

原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了4,因此最终结果为16

闭包的两种主要用法:

  • 在返回的对象中,实现了一个闭包,该闭包携带了局部变量x,并且,从外部代码根本无法访问到变量x。换句话说,闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来。

'use strict';

function create_counter(initial) {
    var x = initial || 0;
    return {
        inc: function () {
            x += 1;
            return x;
        }
    }
}

//使用
var c1 = create_counter();
c1.inc(); // 1
c1.inc(); // 2
c1.inc(); // 3

var c2 = create_counter(10);
c2.inc(); // 11
c2.inc(); // 12
c2.inc(); // 13
  • 闭包还可以把多参数的函数变成单参数的函数。

'use strict';

function make_pow(n) {
    return function (x) {
        return Math.pow(x, n);
    }
}

// 创建两个新函数:
var pow2 = make_pow(2);
var pow3 = make_pow(3);

console.log(pow2(5)); // 25
console.log(pow3(7)); // 343
  1. 一个立即执行的匿名函数

(function (x) {
    return x * x;
})(3); //注意函数体要用()扩住,否则会报语法错误
  1. 箭头函数

x => x * x
//相当于
function (x) {
    return x * x;
}
//统一格式:
传入的参数=>函数体操作;//这是只包含一个表达式的操作
传入参数=>{
    多行操作,需要有return返回值
}                   //函数体的写法
  1. generator

用来返回多个值

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值