并发解决的问题:速度 和设计可管理性 。
更快的执行 :
并发用于多处理器系统中可以吞吐量,但是并发通常却用来提高单处理器 上的程序性能。如果但处理器没有阻塞 ,那么多线程需要线程上下文的转换,程序性能反而会更差,因此之所以在但处理器中需要多线程,是因为程序控制范围之外的阻塞引起的,如果没有任务阻塞,那么在但处理器上使用并发就没有任何意义。
单处理器上性能提高的常见示例是事件驱动编程。实际上,使用并发的最吸引人的一个优势就是可以产生具有可相应的用户界面。如果没有多线程,那么你的任何一段代码都必须检查界面的元素的状态以作出界面反应。
并发的最直接的方式是操作系统级别使用进程。进程是运行在自己的地址空间内的自包容的程序。多任务操作系统通过进程之间的切换实现同时运行多个进程(程序)。并发的理想示情况是每个任务都作为进程在其自己的地址空间执行,因此任务之间不可能相互干涉。
函数型语言,Erlang等,每个函数调用都不会产生任何副作用(并因此不能干涉其他函数),因此可以作为独立的任务来驱动。函数型语言包含了对针对任务之间彼此通信的安全机制。如果你发现程序中的某一个部分必须大量使用并发,并且你在试图共建这个部分时碰到了过多的问题,那么你可以考虑使用函数型语言来解决这个问题。
java采取了更加传统的方式,线程机制是在顺序型语言的基础上提供了对线程的支持。与在多任务操作系统的分叉外部进程不同,线程机制是在由执行程序表示的单一进程中创建任务。这种方式的好处是操作系统的透明性,这是java的一个重要设计目标。像在单任务操作系统(比如OSX之前的Macintosh操作系统),除非在java中添加多处理器机制,否则任何并发的java程序都无法移植到单任务操作系统,这就打破了“编写一次,到处运行”的要求。
改进代码的设计 :
并发提供了一种结构上的好处,如果没有并发,某些类型的问题,例如仿真,没有并发是很难解决的。仿真的实例有:计算机游戏或者电影中的生动的动画,这都通常涉及到很多交互式元素,看似每个都有“自己的想法”。
然而仿真往往涉及到非常大的任务,而多线程系统对线程支持的数量往往比较小,而且还可能依赖与平台,或者在java中就是java的版本。解决这个问题的一个典型方法是协作多线程。java的线程机制是抢占式的,这表示调度机制会周期性的终端线程,将上下文切换到另外一个上下文,从而为每一个线程踢狗实践派,使得每一个线程都得到合理的时间去驱动它的任务。在协作式的系统中,每个任务都会自动的放弃控制,这要求程序员要有意识的在每个任务中插入某种让步语句。写作时的系统优势是双重的:上下文的切换通常比抢占式的低廉很多,并且对可以同时执行的线程的数量在理论上没有限制,但是某些协作式系统并未设计为多处理器之间的分布任务,这可能会非常受限。
消息系统设计分布在整个网络中的多台独立的计算机,因此并发就会成为一种非常有用的模型,因为它是实际发生的模型。这种情况下,所有的进程都彼此独立的运行,甚至没有任何可能去共享资源。但是必须同步进程之间的信息。
并发需要代价,包括复杂性代价,但是这些代价相对于程序设计、资源负载均衡以及用户方便使用方面的改进相比,就显得微不足道了。通常,线程使你能够创建更加松散耦合的设计,否则,你的代码中的各个部分都必须显式的关注那些通常可以由线程来处理的任务。