多线程tips(面试常用)
- 描述线程和进程的区别?
我们运行一个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(面试常用)的更多相关文章
- php开发面试题---面试常用英语(你能介绍你自己吗?)
php开发面试题---面试常用英语(你能介绍你自己吗?) 一.总结 一句话总结: Could you please describe yourself? 1.为什么觉得自己适合这份工作? Why do ...
- Java && Python 算法面试常用类以及方法总结
数据结构 逻辑结构上: 包括集合,线性结构,非线性结构. 存储结构: 顺序存储,链式存储,索引存储,散列存储. Java 常见数据结构 大专栏 Java && Python 算法面试 ...
- 并发和多线程-说说面试长提平时少用的volatile
说到volatile,一些参加过面试的同学对此肯定不陌生. 它是面试官口中的常客,但是平时的编码却很少打照面(起码,我是这样的). 最近的面试,我也经常会问到volatile相关的问题,比如volat ...
- Docker 入门 到部署Web 程序- (阿里面试常用的docker命令和优点)
最近阿里的面试官问我Docker是做什么用的,我记得之前360和美团,京东的都问过,但是一直没时间看,最近有时间了,系统的学习了一下Docker,在此做一下记录,方便各位看官学习交流 一.Docker ...
- Java多线程基础(面试向)
----?为什么要用到多线程 CPU是以时间片的方式为进程分配CUP处理时间的,如果当一个进程同时要完成几件事的时候,如当从网上下载文件的时候,需要一边下载一边显示进度而且还要一边保存,如果按照单线程 ...
- Java多线程并发面试问答
Java并发面试问答 什么是原子操作?Java并发API中的原子类是什么? 原子操作在单个任务单元中执行,而不受其他操作的干扰.在多线程环境中,原子操作是必需的,以避免数据不一致. int++不是原子 ...
- ios多线程开发的常用三种方式
1.NSThread 2.NSOperationQueue 3.GCD NSThread: 创建方式主要有两种: [NSThread detachNewThreadSelector:@selector ...
- Python简单的多线程demo:常用写法
简单多线程实现:启动50个线程,并计算执行时间. import threading import time def run(n): time.sleep(3) print("task:&qu ...
- Java多线程-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-从一个错误的双重校验锁 ...
随机推荐
- noip200605能量项链
题解: 状态转移方程为:dp[i][j] = max{dp[i][k] + dp[k+1][j] + a[i]*a[k+1]*a[j+1]}, k=i, ..., j-1, i和j都从1开始.dp[i ...
- OS Tools-GO富集分析工具的使用与解读详细教程
我们的云平台上的GO富集分析工具,需要输入的文件表格和参数很简单,但很多同学都不明白其中的原理与结果解读,这个帖子就跟大家详细解释~ 一.GO富集介绍: Gene Ontology(简称G ...
- 数据迁移工具Sqoop和DataX功能比较
本文转载自: http://www.cnblogs.com/panfeng412/archive/2013/04/29/data-migration-tool-sqoop-and-datax.html ...
- TCP客户端图片上传服务端保存本地示例
//TCP客户端public class TCPClient { public static void main(String[] args)throws IOException { Socket s ...
- 利用PHP将图片转换成base64编码的实现方法
先来说一下为什么我们要对图片base64编码 base64是当前网络上最为常见的传输8Bit字节代码的编码方式其中之一.base64主要不是加密,它主要的用途是把某些二进制数转成普通字符用于网络传输. ...
- windows.onload和body的onload属性的区别
关于windows.onload和body的onload属性的区别网上有些说法说的也不太统一,现在系统说下: 先看共同点: 都是body内容体加载结束执行: window.onload 内部方式可以 ...
- 第二节 JavaScript基础
JavaScript组成及其兼容性: ECMAScript:解释器,翻译,用于实现机器语言和高级语言的翻译器:几乎没有兼容性问题 DOM(Document Object Model):文档对象模型,文 ...
- OLED屏幕那些次像素有趣的排列方式
http://www.dzsc.com/data/2016-6-2/109856.html 我们今天的重点内容为倒数第二列内容的上半部分,也就是RGB排列和Pentile排列.在介绍OLED屏幕时候我 ...
- django crontab 定时任务
分 时 日 月 周 命令(最好用绝对路径)比如: * * * * * rm -fr /mnt/* //每分钟执行一次对/mnt目录下文件的删除*/2 * * * * rm -fr /mnt/* //每 ...
- nlp homework 03
NLP Homework 03 --冯煜博 题目描述 (盒子和球模型)假设有3个盒子,每个盒子里装有红白两种颜色的球,盒子里的红白球有下表列出,初始状态分布. 解答 1. 给出HMM模型 \(\mu= ...