异步原理以及实现方式
参考文档:https://www.cnblogs.com/haiyoune2/p/9243693.html
原理
- 同步和异步通信
- 步调用不阻塞线程,而是把调用塞到线程池中,程序主线程或UI线程可以继续执行
- 异步是借助于多线程来实现的
- 一句话概括:程序无须按照代码顺序自上而下执行
实现方式
- C# 5.0 新增async/await关键字,可以简化异步编程
- 使用async关键字,对方法标记为异步(async本身不会创建异步操作,如果没有await关键字,编译器会警告但不报错,将以同步形式执行程序)
- BeginInvoke实现
- Timer定时器实现
多线程原理以及跨线程交互实现方式
多线程原理
-
什么是进程?
当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。 而一个进程又是由多个线程所组成的。 -
什么是线程?
线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。 -
什么是多线程?
多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
跨线程交互实现方式
基于委托方式进行实现
private delegate void DelegateInfo();
private delegate void DelegateIsEnd();
//这个是线程调用其他线程的方法
private void Dowork()
{
// 判断是否需要Invoke,多线程时需要
if (this.InvokeRequired)
{
// 通过委托调用写主线程控件的程序,传递参数放在object数组中
this.Invoke(new DelegateInfo(LoadFile));
}
else
{
// 如果不需要委托调用,则直接调用
this.LoadFile();
}
//=========线程结束===========
this.BeginInvoke(new DelegateIsEnd(ISEnd));
}
private void ISEnd()
{
wf.Visible = false;
wf.Close();
wf.Dispose();
}
private void LoadFile()
{
}
private WaitingForm wf = nu
GC原理以及实现方式
GC原理
简单来说,是标记与清除
- 标记
从应用程序的root出发,利用相互引用关系,遍历其在Heap上动态分配的所有对象,没有被引用的对象不被标记,即成为垃圾;存活的对象被标记,即维护成了一张“根-对象可达图”。 - 清除
启用Compact算法,对内存中存活的对象进行移动,修改它们的指针,使之在内存中连续,使空闲的内存连续,从而解决内存碎片问题,当再次为新对象分配内存时,CLR不必在充满碎片的内存中寻找适合新对象的内存空间,所以分配速度会大大提高。注意:大对象(large object heap)除外,GC不会移动一个内存中巨无霸,它会被放到一个特殊的内存空间中。
IOC容器实现原理,DI实现方式
MVC
MVC生命周期
数据库的锁,netcore的锁,数据库索引,分布式相关
项目的架构 分布式 oauth2 openid clr
Net core? 依赖注入,什么是中间件?
AOP、多线程Task thread pool,并发冲突
AOP面向切面编程
异常捕获,如何控制线程的并发访问数量?
各种数组类型、数组与集合的区别。
什么是委托?Action与Function的区别?
委托概述
委托是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。
Action与Function区别
- 相同:内置委托类型,顾名思义Action和Func本身就是已经定义好的委托类型。
- 区别:Action委托签名不提供返回类型,而Func提供返回类型。
Redis场景?数据类型?为什么速度、分布式锁? 大规模秒杀
如何保证缓存与数据库双写时的数据一致性?CAP
缓存雪崩和缓存穿透问题解决?
数据库的锁类型?共享 排他 更新锁
数据库系统角度
- 排他锁
- 共享锁(Share Lock)
- 多个事务可封锁同一个共享页
- 任何事务都不能修改该页
- 通常是该页被读取完毕,读锁立即被释放
- sqlserver使用 with(HOLDLOCK)
- 更新锁
程序员角度
- 悲观锁
- 乐观锁
悲观锁和乐观锁的区别?如何实现乐观锁悲观锁?
索引 mysql索引的方式
事务隔离级别 默认分布式事务
EF里如何避免脏读
脏读定义
- 当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的
如果避免脏读
- 设置事务隔离级别TRANSACTION_READ_COMMITTED,常用防止脏读
设计模式 k8s docker 队列 linux
装箱的底层原理;装箱、拆箱过程中的性能损失,如何避免装箱彼此相过程中的性能损失;
装箱的底层原理
- 所有的值类型都继承自System.ValueType,而System.ValueType继承自System.Object。
- 所有的值类型对象都分配在堆栈上,而所有的引用类型包括System.Object对象都分配在堆上。
- CLR需要做额外的工作把堆栈上的值类型移动到堆上,这个操作就被称为装箱。
- 在堆上分配一个内存空间,大小等于需要装箱的值类型对象的大小加上两个引用类型对象都拥有的成员:类型对象指针和同步块引用。
- 把堆栈上的值类型对象复制到堆上新分配的对象。
- 返回一个指向堆上新对象的引用,并且存储到堆栈上被装箱的那个值类型的对象里。
如何避免装箱彼此相过程中的性能损失
- 尽量减少装箱拆箱操作
- 通过泛型解决
- 在循环里外,提前进行装箱
多线程锁的类型
- 原子操作(Interlocked)
所有方法都是执行一次原子读取或一次写入操作。 - lock()
避免锁定public类型,否则实例将超出代码控制的范围,定义private对象来锁定。 - Monitor实现线程同步
通过Monitor.Enter() 和 Monitor.Exit()实现排它锁的获取和释放,获取之后独占资源,不允许其他线程访问。还有一个TryEnter方法,请求不到资源时不会阻塞等待,可以设置超时时间,获取不到直接返回false。 - ReaderWriterLock
当对资源操作读多写少的时候,为了提高资源的利用率,让读操作锁为共享锁,多个线程可以并发读取资源,而写操作为独占锁,只允许一个线程操作。 - 事件(Event)类实现同步
事件类有两种状态,终止状态和非终止状态,终止状态时调用WaitOne可以请求成功,通过Set将时间状态设置为终止状态。- AutoResetEvent(自动重置事件)
- ManualResetEvent(手动重置事件)
- 信号量(Semaphore)
信号量是由内核对象维护的int变量,为0时,线程阻塞,大于0时解除阻塞,当一个信号量上的等待线程解除阻塞后,信号量计数+1。线程通过WaitOne将信号量减1,通过Release将信号量加1,使用很简单。 - 互斥体(Mutex)
独占资源,用法与Semaphore相似。 - 跨进程间的同步
通过设置同步对象的名称就可以实现系统级的同步,不同应用程序通过同步对象的名称识别不同同步对象。
网友评论