zoukankan      html  css  js  c++  java
  • 《CLR via C#》读书笔记

      11年11月份读完《Beginning C# Object》两个月了,期间使用C#重写了原来用C语言实现的矢量地图引擎,有了几万行代码的实践,也用面向对象思想设计重构了引擎,引擎质量提高了一个数量级,可读性、可维护性、性能都有提高;对C#语言的学习更多是在MSDN的文档、《Programming windows phone 7》英文pdf的阅读,结合windows phone平台的使用中,没有系统性的深入学习。因此买了《CLR via C#》、《深入Java虚拟机》两本书,一本老外写的,一本国人写的;一个刚开始学的CLR平台,一个较为熟悉的JVM平台,两者对照学习;JVM的书写的较为简练,更熟悉,读得相对快一些,CLR的书老外的风格,细节、背景很多,页数是JVM的几倍,刚开始觉得啰嗦,需要耐心精心读下去,弄懂每个技术点的来龙去脉,对技术的深入理解收获良多,《Programming windows phone 7》相对Android的文档也是这种感受,写下《CLR via C#》的一些读书笔记:

    CLR:定义了一致的语义集、屏蔽上层不同语言的不同语法;用类似汇编语言的中间语言IL描述;

    .NET框架类库:让开发人员日子好过一些的常用类。

      最近需要用到多线程,前面读了6章,就先看线程部分救急了:

    1.进程是系统分配资源的单位,有虚拟进程空间,可以实现进程间隔离,使得系统健壮安全,不会因为一个应用崩溃而死掉;线程是系统调度的单位,逻辑的CPU,线程有一个标识表明自己所属的进程,线程大概30ms进行一次线程切换,使得OS不会因为一个长时间的任务执行而阻塞不响应用户交互,且可利用多CPU;CLR中的用户线程一一对应一个windows的内核线程(当前JVM的windows、Linux版也是,Linux中线程可理解为共享进程空间的进程),要区分用户模式与内核模式运行,两种模式切换也耗费较多资源;

      线程创建:thread = new Thread(threadOp(param)),thread.Start()启动,Thread.Sleep(), Abort()停止;

    2.超线程:硬件概念,为了减少线程上下文切换的消耗,有了超线程的概念,一个CPU只有一组执行资源,但有多组CPU寄存器的线程上下文中需要的资源;

      默认线程上下文有父线程流向子线程,ExectionContext.SuppressFlow()可以阻止流动,提高性能。

      中断上下文与任何进程无关,运行在内核空间。

    3.线程池:创建线程耗费资源虽然较进程少,但仍需要线程栈、CPU寄存器等线程上下文,为了减少重复线程创建的消耗,引入了线程池,即创建的线程执行完后不立即结束,由线程池管理,可以重复利用;Thread.QueueUserWorkItem、System.Threading.Timer、TaskScheduler将工作项放到CLR线程池的全局队列中,每个线程再从全局队列取任务到自己的本地工作项线程中;线程池的线程分两种:用于计算的工作者worker线程、用于APM异步IO的IO线程;

      计算操作:ThreadPool.QueueUserWorkItem(computeOp, param);将计算操作computeOp加入线程池操作队列;

        计算操作中间取消:使用CancellationTokenSource,在computeOp中判断;

      IO异步操作:外设如硬盘等可认为是一个微型计算机,CPU给外设任务后,不需要阻塞等待,外设完成任务后以中断方式,通知CPU,再处理外设返回的结果即可;也不需要为每次IO或者每个外设建立一个线程,通过线程池将向外设发送的任务、外设返回结果的处理都通过异步方式作为任务项加入线程池;通常调用BeginXXX(callBack,param)后CLR返回一个唯一标识IO请求IAsyncResult对象,该对象的AsyncState属性为param,param可以存放httpRequest等参数,线程池调用回调函数时通过EndXXX(IAsyncResult)得到外设返回的结果。

        注意点:EndXXX应该唯一调用一次;异步IO操作通常不能取消,只能放弃返回结果;基于Event的EAP模式也可实现某些异步IO(消息队列方式);

    4.任务:线程池解决了线程重复创建的消耗,任务解决操作什么时候完成、返回执行结果的问题;新建Task,start()启动,通过task.Wait()等待任务结束;task.ContinueWith(anotherTask)该任务结束后,启动另一个任务;

    5.Timer:有两种

      System.Threading.Timer:可将后台任务定期加入线程池;使用注意点:保持timer对象存活防止GC,timer = new Timer(timeOp,param,delayTime,TimeOut.Infinite(-1)),第一次加入时只调用一次,在timeOp中通过timer.Change(delayTime, TimeOut,Infinite)再次加入一次任务;

      System.Windows.Threading.DispatcherTimer:前台,通常用于GUI,将硬件计时器与该线程关联,中断方式将消息加入线程的消息队列;执行回调方法的线程就是设置计时器的线程;如用于向刷新界面的主线程发送消息的System.Windows.Threading.Dispatcher;用法 DispatcherTimer dispatcherTimer = new DispatcherTimer(); dispatcherTimer.Tick += new EventHandler(DispatcherTimerTick);dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 300);dispatcherTimer.Start();dispatcherTimer.Stop();private void DispatcherTimerTick(object sender, EventArgs e){}

    6.同步:解决多线程带来的数据读写的线程安全问题,多线程并且可能同时访问的数据才需要同步,如UI界面通过消息队列处理消息则不需要同步,同步分为4种:

      用户模式锁:乐观锁,通过自旋spin的方式,即不使用内核模式的锁,浪费CPU时间,乐观等待其他线程释放锁;如Thread.SpinWait(time);其它如Thread.VolatileWrite(ref,int)、volatile变量、Interlocked中的方法可进行简单的原子操作;

      内核模式锁:悲观锁,需要转换内核模式,比用户模式锁消耗更多时间;AutoResetEvent、ManualResetEvent基于内核的Boolean变量,Semaphore基于内核的Int32变量,Mutex为互斥锁,线程独有,可重复拥有;

      混合锁:混合使用用户模式锁和内核模式锁,由JIT编译器优化,通常先自旋再内核阻塞;如Monitor、ReaderWriterLockSlim等;lock(obj){}是Monitor的语法糖;CLR中实例对象、类对象都有一个同步块索引项,初始-1,Monitor.Enter(obj)后指向一个同步块,同步块中含有对应的内核锁、在该同步块上等待的线程、现在拥有同步块的线程ID等字段,Monitor.Exit(obj)释放锁。

        类似Java的synchronized(obj){}语法糖。

      条件变量模式:结合Monitor、运行条件实现;Monitor.Enter(obj)获得锁,通常在while(条件)循环中条件不满足时通过Monitor.Wait(obj)暂时释放锁,另一个线程通过Monitor.Enter(obj)获得锁后,通过Monitor.Pulse(obj)或者Monitor.PulseAll(obj)唤醒Wait的线程,并Monitor.Exit(obj)释放锁后,在锁上Wait被唤醒的线程可以继续参与运行调度。

        Java中每个Object都有wait()、notify()方法,使用更方便,但是CLR的Monitor语义更好理解。

    7.一些语法糖:Parallel.For、ForEach、Invoke一次将多个操作加入线程池;lock(obj){}是try{Monitor.Enter(obj)}finally{Monitor.Exit(obj)};

  • 相关阅读:
    poj3278 Catch That Cow
    poj2251 Dungeon Master
    poj1321 棋盘问题
    poj3083 Children of the Candy Cor
    jvm基础知识—垃圾回收机制
    jvm基础知识1
    java面试基础必备
    java soket通信总结 bio nio aio的区别和总结
    java scoket aIO 通信
    java scoket Blocking 阻塞IO socket通信四
  • 原文地址:https://www.cnblogs.com/toven/p/2278204.html
Copyright © 2011-2022 走看看