• 描述线程和进程的区别?
我们运行一个exe,就是一个进程实例,系统中有很多个进程。每一个进程都有自己的内存地址空间,每个地址相当于一个独立的边界,有自己独占的资源,进程之间不能共享代码和数据空间。(可用SendMessage实现进程之间消息传递)每一个进程有一个或多个线程,进程内多个线程可以共享所属进程的资源和数据,线程是操作系统调度的基本单元。线程是操作系统来调度和执行的。
当我们创建了一个线程后,线程里面到底有些什么东西呢?主要包括线程内核对象、线程环境块、1M大小的用户模式栈、内核模式栈。其中用户模式栈对于普通的系统线程那1M是预留的,在需要的时候才会分配,但是对于CLR线程,那1M一开始就分配了内存空间的。CLR线程是直接对应于一个Windows线程的。
还记得以前学校里学习的计算机课程里讲到,计算机的核心计算资源就是CPU核心和CPU寄存器,这也就是线程运行的主要战场。操作系统中那么多线程(一般都有上千个线程,大部分都处于休眠状态),对于单核CPU,一次只能有一个线程被调度执行,那么多线程怎么分配的呢?Winsows系统采用时间轮训机制,CPU计算资源以时间片(大约30ms)的实行分配给执行线程。 计算机资源(CPU核心和CPU寄存器)一次只能调度一个线程,具体的调度流程: 1.把CPU寄存器内的数据保存到当前线程内部(线程上下文等地方),给下一个线程腾地方;
2.线程调度:再线程集合里取出一个需要执行的线程;
3.加载新线程的上下文数据到CPU寄存器;
4.新线程执行,享受她自己的CPU时间片(大约30ms),完了之后继续回到第一步,继续轮回; 上面线程调度的过程,就是一次线程切换,一次切换就涉及到线程上下文灯数据的搬入搬出,性能开销很大的。因此线程不可滥用,线程的创建和消费也是和昂贵的,这也是为什么建议尽量使用线程池的一个主要原因。 对于Thread的使用太简单了,不重复了,总结一下线程的主要几点性能影响: 1、线程的创建、销毁时很昂贵的; 2.线程上下文切换有极大的性能开销,当然假如需要调度的新线程与当前是同一线程的话,就不需要线程上下文切换了,效率也要快很多。
3、这一点需要注意,GC执行回收时,首先(安全的)要挂起所有线程,遍历所以线程栈(根),GC回收后更新所有线程的根地址,再恢复线程调用,线程越多,GC要干的活就越多; 当然现在硬件的发展,CPU的核心越来越多,多线程技术可以极大提高应用程序的效率。但这也是必须在合理利用多线程技术的前提下,了解线程的基本原理,然后根据实际需求,好药注意相关资源环境,如磁盘IO、网络等情况综合考虑。
  • 为什么GUI不支持跨线程调用?有什么解决方法?
这是很多开发C/S客户端应用程序会遇到的问题,GUI程序的界面控件不允许跨县城访问,如果在其他线程中访问了界面控件,运行时就会抛出一个异常,就像下面的图示,是不是很熟悉,这其中的罪归祸首就是,就是“GUI的线程处理模型“,GUI应用程序(主要是Winform、wpf)引入了一个特殊线程处理模型,UI控件元素只能由创建它的线程访问和修改,微软这样处理是为了保证UI控件的线程安全。
为什么在UI线程执行一个耗时的计算操作,会导致UI假死呢?这个问题要追溯到Windows的消息机制了。 因为Windows是基于消息机制的,我们在UI上所有的键盘、鼠标操作都是以消息的形式发送给各个应用程序的。 GUI线程内部就有一个消息队列,GUI线程不断的循环处理这些消息,并根据消息更新UI的呈现。如果这个时候, 你让GUI线程去处理一个耗时的操作(比如花10秒去下载一个文件),那GUI线程就没办法处理消息独立饿了, UI界面就处于假死状态。
那我们该怎么办呢?不难想到使用线程,拿在线程里处理事件完成后,需要更新UI控件的状态,又该怎么办呢?
常用几种方式: 1.使用GUI控件提供的方法,Winform是控件的Invoke方法,wpf中控件的Dispatcher.Invoke方法
2.使用.net中提供的backgroundWorker执行耗时计算操作,在其任务完成事件RunWorkCompleted中更新UI控件
3.看上去很高大上的方法:使用GUI线程处理模型的同步上下文来送封UI控件修改操作,这样可以不需要调用UI控件元素
  • 前台线程和后台线程的区别
应用程序必须运行完所有的前台线程才可以退出,或者主动结束前台线程,不管后台线程是否还在运行,应用程序都会结束;对于后台线程,应用程序则不考虑是否已经运行完毕而直接退出,所以的后台线程在应用程序退出时自动结束。
通过将Thread.isBackground设置为True,就可以将线程指定为后台线程,主线程就是一个前台线程。
  • 说说常用的锁,lock是一种什么样的锁?
常用的如如SemaphoreSlim、ManualResetEventSlim、Monitor、ReadWriteLockSlim,lock是一个混合锁,其实质是Monitor
  • lock为什么要锁定一个参数(可否为值类型?)参数有什么要求?
lock的锁对象要求为一个引用类型。她可以锁定值类型,但值类型会被装箱,每次装箱后的对象都不一样,会导致锁定无效。
对于lock锁,锁定的这个对象参数才是关键,这个参数的同步索引块指针会指向一个真正的锁(同步块),这个锁(同步块)会被复用。
  • 多线程和异步的区别和联系
  • 线程池的优点和不足
线程池的使用是非常简单的,如下面的代码,把需要执行的代码提交到线程池,线程池内部会安排一个空闲的线程来执行你的代码,完全不用管理内部是如何进行线程调度的。

ThreadPool.QueqeUserWorkItem(t=>Console.WriteLine("Hello thread pool"));

每个CLR都有一个线程池,线程池在CLR内可以多个AppDomain共享,线程池是CLR内部管理的一个线程集合,初始是没有线程的,在需要的时候才会创建。线程池的主要结构图如下,基本流程如下:

 1.线程池内部维护一个请求列队,用于缓存用户请求需要执行的代码任务,就是Thread.QueqeUserWorkItem提交的请求;

 2.有新任务后,线程池使用空闲线程或者新线程来执行队列请求;

 3.任务执行完后线程不会销毁,留着重复使用;

 4.线程池自己负责维护线程的创建和销毁,但线程池有大量闲置的线程是,线程池会自动结束一部分多余的线程来释放资源;

线程池是有一个容量的,因为他是一个池子吗,可以设置线程池的最大活跃线程数,调用方法Threadpool.SetMaxThreads可是设置相关参数,但很多线程实践里都不建议程序猿们自己去设置这些参数,其实微软为了提高线程池性能,做了大量的优化,线程池可以很智能的确定是否要创建或者消费线程,大多数情况都可以满足需求了。线程池使得线程可以充分有效的被利用,减少了任务启动的延迟,也不用大量的去创建线程,避免了大量线程的创建和销毁对性能造成极大影响。

上面了解了线程的基本原理和诸多优点后,如果你是一个爱思考的猿类,应该会很容易的发现很多疑问,比如把任务添加到线程池队列后,怎么取消和挂起呢?如何知道他执行完了呢,下面来总结一下线程池的不足:

 1.线程池内的线程不支持线程的挂起、取消等操作,如想要取消线程池的任务,.net支持一种协作方式取消,使用起来也不少很方便,而且有些场景并不是很满足需求;

 2.线程内的任务没有返回值,也不知道何时执行完成;

 3.不支持设置线程的优先级,还包括其他类似需要对线程有更多的控制的需求也不支持;
  • Mutex和lock有什么不同?一般用哪一种比较好?
Mutex是一个基于内核模式的互斥锁,支持锁的递归调用,而Lock是一个混合锁,一般建议使用Lock更好,因为lock的性能更好。

多线程tips(面试常用)的更多相关文章

  1. php开发面试题---面试常用英语(你能介绍你自己吗?)

    php开发面试题---面试常用英语(你能介绍你自己吗?) 一.总结 一句话总结: Could you please describe yourself? 1.为什么觉得自己适合这份工作? Why do ...

  2. Java && Python 算法面试常用类以及方法总结

    数据结构 逻辑结构上: 包括集合,线性结构,非线性结构. 存储结构: 顺序存储,链式存储,索引存储,散列存储. Java 常见数据结构 大专栏  Java && Python 算法面试 ...

  3. 并发和多线程-说说面试长提平时少用的volatile

    说到volatile,一些参加过面试的同学对此肯定不陌生. 它是面试官口中的常客,但是平时的编码却很少打照面(起码,我是这样的). 最近的面试,我也经常会问到volatile相关的问题,比如volat ...

  4. Docker 入门 到部署Web 程序- (阿里面试常用的docker命令和优点)

    最近阿里的面试官问我Docker是做什么用的,我记得之前360和美团,京东的都问过,但是一直没时间看,最近有时间了,系统的学习了一下Docker,在此做一下记录,方便各位看官学习交流 一.Docker ...

  5. Java多线程基础(面试向)

    ----?为什么要用到多线程 CPU是以时间片的方式为进程分配CUP处理时间的,如果当一个进程同时要完成几件事的时候,如当从网上下载文件的时候,需要一边下载一边显示进度而且还要一边保存,如果按照单线程 ...

  6. Java多线程并发面试问答

    Java并发面试问答 什么是原子操作?Java并发API中的原子类是什么? 原子操作在单个任务单元中执行,而不受其他操作的干扰.在多线程环境中,原子操作是必需的,以避免数据不一致. int++不是原子 ...

  7. ios多线程开发的常用三种方式

    1.NSThread 2.NSOperationQueue 3.GCD NSThread: 创建方式主要有两种: [NSThread detachNewThreadSelector:@selector ...

  8. Python简单的多线程demo:常用写法

    简单多线程实现:启动50个线程,并计算执行时间. import threading import time def run(n): time.sleep(3) print("task:&qu ...

  9. Java多线程-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier

    Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-从一个错误的双重校验锁 ...

随机推荐

  1. js函数集

    js函数集·字符串(String) 1.声明 var myString = new String("Every good boy does fine."); var myStrin ...

  2. 微信小程序制作家庭记账本之二

    第二天,继续学习制作记账本,网上搜寻别人的源码进行学习,但是搜寻过程中总是能看到github这个东西,不清楚这是什么东西,明天继续努力吧.

  3. Django MTV simple_tag filter inclusion_tag

    Django框架 模型(Model).视图(View)和控制器(Controller),具有耦合性低.重用性高.生命周期成本低等优点. MVC 框架 --  Model -View -Controll ...

  4. webpack系统配置

    简言之,webpack 是一个模块打包器 (module bundler),能够将任何资源如 JavaScript 文件.CSS 文件.图片等打包成一个或少数文件. 为什么要用Webpack? 首先, ...

  5. 数据库中的undo日志、redo日志

    MySQL中有六种日志文件,分别是:重做日志(redo log).回滚日志(undo log).二进制日志(binlog).错误日志(errorlog).慢查询日志(slow query log).一 ...

  6. 大数据自学4-Hue集成环境中各模组说明

    前面已经学习了如何将数据从关系型数据库导入到Hive/HDFS,并且在Windows客户端查询导入的数据,接下来继续学习CDH,知识点: 1.Hue环境中DB Query如何使用,DB Query这个 ...

  7. Powerpoint 演示时定时提醒工具

    经常碰到这样的场景,规定的演讲报告时间所剩无几,甚至是已经超时,但演讲者并不知情,做为主持人只能从旁边轻轻的善意的提醒,但有时演讲者会没注意到主持人的提醒... 这里要介绍的就是这样一款用于提醒演讲者 ...

  8. 【javascript】对原型对象、原型链的理解

    原型对象,原型链这些知识属于基础类知识.但是平时开发过程中也很少用到. 看网上的意思,原型链用于es5开发场景下的继承.es6有了类语法糖之后,就自带继承了. 通过理解,个人画了一张原型链解构的关系图 ...

  9. log4j2笔记 #02# 启用异步日志

    索引 参考 Making All Loggers Asynchronous 第一步,添加相应的disruptor库 第二步,设置系统属性log4j2.contextSelector 第三步,检验! 参 ...

  10. Cannot convert value of type [java.lang.String] to required type [javax.sql.DataSource] for property 'dataSource': no matching editors or conversion strategy found

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFa ...