C#.NET 面试题 初级篇(四)
线程与进程的区别?
线程(Thread)与进程(Process)二者都定义了某种边界,不同的是进程定义的是应用程序与应用程序之间的边界,不同的进程之间不能共享代码和数据空间,而线程定义的是代码执行堆栈和执行上下文的边界。一个进程可以包括若干个线程,同时创建多个线程来完成某项任务,便是多线程。
而同一进程中的不同线程共享代码和数据空间。用一个比喻来说,如果一个家庭代表一个进程,在家庭内部,各个成员就是线程,家庭中的每个成员都有义务对家庭的财富进行积累,同时也有权利对家庭财富进行消费,当面对一个任务的时候,家庭也可以派出几个成员来协同完成,而家庭之外的人则没有办法直接消费不属于自己家庭的财产。
前台线程和后台线程有什么区别?
通过将 Thread.IsBackground 属性设置为 true,就可以将线程指定为后台线程
前台线程: 应用必须结束掉所有的前台线程才能结束程序,只要有一个前台线程没退出进程就不会自动退出,当然线程是依附在进程上的,所以你直接把进程 KO 掉了的话自然所有前台线程也会退出。
后台线程: 进程可以不考虑后台直接自动退出,进程自动退出后所有的后台线程也会自动销毁。
什么是互斥?
当多个线程访问同一个全局变量,或者同一个资源(比如打印机)的时候,需要进行线程间的互斥操作来保证访问的安全性。
Task 状态机的实现和工作机制是什么?
CPS 全称是 Continuation Passing Style,在.NET 中,它会自动编译为:
1、将所有引用的局部变量做成闭包,放到一个隐藏的状态机的类中;
2、将所有的 await 展开成一个状态号,有几个 await 就有几个状态号;
3、每次执行完一个状态,都重复回调状态机的 MoveNext 方法,同时指定下一个状态号;
4、MoveNext 方法还需处理线程和异常等问题。
说说常用的锁,lock 是一种什么样的锁?
常用的锁如 SemaphoreSlim、ManualResetEventSlim、Monitor、ReadWriteLockSlim,lock 是一个混合锁,其实质是 Monitor
lock 为什么要锁定一个参数(可否为值类型?)参数有什么要求?
lock 的锁对象要求为一个引用类型。她可以锁定值类型,但值类型会被装箱,每次装箱后的对象都不一样,会导致锁定无效。
对于 lock 锁,锁定的这个对象参数才是关键,这个参数的同步索引块指针会指向一个真正的锁(同步块),这个锁(同步块)会被复用。
多线程和异步的区别和联系?
多线程是实现异步的主要方式之一,异步并不等同于多线程。实现异步的方式还有很多,比如利用硬件的特性、使用进程或纤程等。
在.NET 中就有很多的异步编程支持,比如很多地方都有 Begin、End 的方法,就是一种异步编程支持,她内部有些是利用多线程,有些是利用硬件的特性来实现的异步编程。
线程池的优点和不足?
优点:
减小线程创建和销毁的开销,可以复用线程;
也从而减少了线程上下文切换的性能损失;
在 GC 回收时,较少的线程更有利于 GC 的回收效率。
缺点:
线程池无法对一个线程有更多的精确的控制,如了解其运行状态等;
不能设置线程的优先级;加入到线程池的任务(方法)不能有返回值;
对于需要长期运行的任务就不适合线程池。
Mutex 和 lock 有什么不同?一般用哪一种比较好?
Mutex 是一个基于内核模式的互斥锁,支持锁的递归调用,而 Lock 是一个混合锁,一般建议使用 Lock 更好,因为 lock 的性能更好。