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

    先用KMP重叠匹配求出各个匹配成功的尾串位置.然后利用DP去求,那转移方程应该是等于 上一个状态 (无法匹配新尾巴) 上一个状态 + 以本次匹配起点为结尾的状态(就是说有了新的位置) + 1 (单单一 ...

  2. .net中的集合

    集合命令空间: 命令空间:类型逻辑上的分类 System.Collections  非泛型集合 System.Collections.Generic 泛型集合 集合内部存数据,实际上都是存到了数组里. ...

  3. Lua语言特色

    [1]多重赋值 多重赋值规则:若值的个数少于变量的个数,那么多余的变量会被赋值为nil 若值的个数多余变量的个数,那么多余的值会被“悄悄地”丢弃掉. 多重赋值应用示例: a, b = , * prin ...

  4. Python OS模块常用功能 中文图文详解

    一.Python OS模块介绍 OS模块简单的来说它是一个Python的系统编程的操作模块,可以处理文件和目录这些我们日常手动需要做的操作. 可以查看OS模块的帮助文档: >>> i ...

  5. django之视图view小知识

    CBV简版流程 AddPublisher.as_view() ——> view 函数 当请求来的时候才执行view view中执行: 1. 先实例化AddPublisher,给self def ...

  6. python 测试文件或者文件目录是否存在 测试文件类型,获取文件大小,获取修改日期

    ----测试一个文件或目录是否存在 >>> import os >>> os.path.exists('/etc/passwd') True >>> ...

  7. hihoCoder #1037 : 数字三角形 (动态规划)

    题目链接:https://hihocoder.com/problemset/problem/1037# 问题描述 小Hi和小Ho在经历了螃蟹先生的任务之后被奖励了一次出国旅游的机会,于是他们来到了大洋 ...

  8. JS3D效果

    <!DOCTYPE html> <html> <head> <title></title> <meta charset="u ...

  9. 面试必问之JVM篇

    前言 只有光头才能变强 JVM在准备面试的时候就有看了,一直没时间写笔记.现在到了一家公司实习,闲的时候就写写,刷刷JVM博客,刷刷电子书. 学习JVM的目的也很简单: 能够知道JVM是什么,为我们干 ...

  10. hibernate自动创建表报表不存在

    在hibernate.cfg.xml配置了<property name="hibernate.hbm2ddl.auto">update</property> ...