并发编程1. 基本概念131029
前言:
这一个领域的学习,主要是C++的多线程编程,同时也会使用C#编程的知识,也就是并发编程,基于Windows编程知识,从系统的内核的底层同步原语,比如线程等等,还有就是.Net的高层同步抽象机制,如线程池、数据同步与控制同步,基本上包括了Windows各种层次的并发概念和机制。还有就是并发编程中的高级主题,比如内存模型与无锁编程、线程、用户图形界面、输入输出等等。
现在在多核的硬件基础之上,软件开发也需要使用并行编程机制。
能耗障碍+内存障碍+ILP障碍 = 限制了串行性能的障碍。
Windows 和.Net 框架对于多线程提供了丰富的支持。Windows在线程调度性能,同步API以及内存层次结构上面持续改进,这样使windows系统能够最大限度的利用硬件资源。
Chapter 1 并发编程的概念概述
程序的架构和并发
代理(Agent):大多数程序都可以理解为一些独立的代理。这里的代理是一个非常抽象的术语,它包括一些专业的属性:1)代理的状态始终是包含在代理的内部;2)代理于外部交互的过程是异步的;3)在同级代理之间的关系是非常松散耦合的。在真是的系统中表现的形式,如web请求,windows基础通信层(windows communication Foundation, WCF)的请求服务,COM组件调用,以及线程中的异步行为。在程序中只存在一个代理,即程序的入口点。(自己写点感想:在学习NodeJs,也就是Server段的JavaScript的时候,有了解过一些关于异步操作的知识,在NodeJs中只有一个线程,但是几乎所有的请求都是异步的,通过一个代理进行处理,具体的话是交给底 层实现,当底层处理完成的时候,就会通知代理返回数据结果,同时在Java中了解过一些模式,其中一个很重要的模式就是)。
任务(Task):代理经常需要执行一些快速的操作,我们将这些操作称之为任务。任务于代理不同之处就是彼此之间的共享状态。
数据:在数据上的许多的操作都是并行的,只要在实现这些操作能够提供潜在的并发,也就是所谓的数据并行。
第一章看的云里雾里的,不知道在说些什么,其实我也是,但是对于windows并发编程还是先从整体上去把握,先了解一下关键词,明白这些关键字是做什么的。我们进入第二章,还是一些概念的知识。
Chapter2 同步和时间
在Windows系统中非常的依赖共享内存(shared Memory)因为进程中的多个线程可以访问相同的虚拟内存地址空间。但是并发的话,会造成许多的问题,也就是所谓的数据竞争(Data Race)和竞态条件(Race Condition),这些问题可能对程序造成崩溃
在并发系统较高的层次去分析状态和同步,并发系统中对于状态管理的三种方式:
彼此独立:确保每一个并发的部分都有自己的一份状态;
不可修改:这种状态以为着共享状态是不可以被修改的;
保持同步:确保系统中多个需要同时访问共享状态的并发部分能够通过一种安全的机制来进行访问。
2.1程序的状态控制
共享状态与私有状态的区分:
系统的状态主要存在于实例域以及静态域,同时在基于线程的系统中,状态还可以保存在分布系统的其他层次中,比如DLL,线程局部存储、运行时以及操作系统资源等等。全局变量和静态变量都可以是共享状态。在创建线程期间传递的任何数据都是共享状态;
状态机与时间:
并发状态要考虑到,在高级语言的已一行代码都会编译成多条指令,因此我们在访问变量修改数据的时候,需要考虑执行的顺序,为了防止出现异常,可以使用临界区(Critical Region)来实现。
同时对于变量,存在读写的问题,使用一个叫做读写锁的机制实现(Read/Write lock)的临界域变量。对于读读冲突(多个线程同时读取相同的共享数据不会存在问题,但是可以使用读写锁的临界域变量为读读冲突提供更好的性能)。
原子性:指的是单个操作或者一组操作,一次被执行,不会被打断,原子操作不能够在更新系统的时候出现故障,如果发生故障必须通过响应的回滚机制恢复之前的状态。
串行化(Serializability):按照两个操作的先后顺序依次执行。(ACID)
2.2同步机制
同步分为数据同步和控制同步。
数据同步:并发访问的串行化,使用的最常见的是互斥技术,声明临界区,通过关键字核函数调用实现:锁机制(Lock), 互斥体(Mutex), 临界区(Critical Section),监视器(Monitor), 二元信号量(Binary Semaphore),以及事务的机制。
协作与控制同步
多个线程之间的依赖性,等待某个事件的发生使用自旋等待,但是自旋等待是十分低效的,因为他会大量占用CPU的计算时间和执行访问内存的操作,从而导致系统总线的通信以及大量的能源消耗。
使用操作系统中的内核等待:当线程进入等得状态的时候,将会触发上下文切换操作箱这个线程李立即从处理器上移走,而且确保Windows线程调度器不会将它作为下一个将要运行的线程,避免了CPU计算资源的浪费,允许其他的线程执行。如
If(!condition){ WaitSysCall(); }
其他的线程需要将condition编程true,而且需要考虑其他班线程也可能正在处于等待状态中,他将通过调用WakeSysCall来唤醒等待中的线程。
激活线程,监视器和条件变量,消息传递。
追梦的飞飞
于广州中山大学 20131029
HomePage: http://yangtengfei.duapp.com