《JAVA 并发编程实战》 第一章:简介

1、并发简史

早期的计算机不包含操做系统,从头至尾只执行一个程序,对于昂贵而且稀有的计算机资源来讲是一种浪费。编程

操做系统的出现使得计算机能运行多个程序,而且不一样的程序都在单独的进程中运行:操做系统为各个独立执行的进程分配各类资源,包括内存。若是须要的话,在不一样的进程之间能够经过一些粗颗粒度的通讯机制来交换数据,包括:套接字、信号处理器、共享内存、信号量以及文件等。缓存

之因此在计算机中加入操做系统来实现多个程序的同时执行,主要是基于如下缘由:安全

  • 资源利用率:等待的同时能够运行另外一个程序
  • 公平性:不是由一个程序从头至尾
  • 便利性:更容易实现

串行编程模型的优点在于直观性和简单性,每次只作一件事情,作完以后再作另外一件。然而并不高效,例如在烤面包的时候,能够去进行其余事情,直到面包烤完,进行通知。但凡作事高效的人,总能在串行性和异步性之间找到合理的平衡,对于程序来讲一样如此。多线程

2、线程的优点

若是使用得当,线程能够有效地额下降程序的开发和维护等成本,同时提高复杂应用程序的性能。线程可以将大部分的异步工做流转换成串行工做流,所以能更好的模拟人类的工做方式和交互方式。此外,线程还能够下降代码的复杂度,使代码更容易编写、阅读和维护。并发

2.1 发挥多处理器的强大能力

因为基本的调度单位是线程,所以若是程序中只有一个线程,那么最多同时只能在一个处理器上运行。 多线程能够同时在多个处理器上执行。若是设计正确,多线程能够经过提升资源利用率来提高系统的吞吐率。异步

2.2 建模的简单性

完成单任务时,很简单,只要把这件事作好就行。可是在完成多任务的时候,不只要把活干好,还要考虑不一样任务之间存在优先级和时间。post

2.3 异步事件的简化处理

一部分线程接受客户端请求,另外一部分处理器请求。若是是单线程程序的话,处理请求时会停顿致使接受请求阻塞,为了不这个问题单线程程序必须使用非阻塞的I/O,这种I/O的复杂性要远远高于同步I/O。性能

3、线程带来的风险

Java对线程的支持实际上是一把双刃剑。虽然Java提供了相应的语言和库,以及一种明确的跨平台内存模型,可是同时提升了对开发人员的技术要求,由于在更多的程序中会使用线程。优化

3.1 安全性问题

线程的安全性多是很是复杂的,在没有充足的状况下,多个线程中的操做执行顺序是不可预测的,甚至会产生奇怪的结果。如下的程序会产生一个整数值序列。操作系统

由于value++ 不是一个原子性的操做:①读取value;②给value+1;③将值写入value。
因为运行时可能有多个线程同时执行了读操做,他们写入时就会发生冲突,从而影响到结果。

3.2 活跃性问题

开发并发模块时,必定要注意线程安全性是不可破坏的。安全性不只对多线程很重要,对于单线程一样重要。此外,线程还会致使一些在单线程程序中不会出现的问题,例如活跃性问题。

安全性的含义是“永远不发生糟糕的事情”,而活跃性则关注另外一个目标:“某件正确的事情最终会发生”。当某个操做没法继续执行下去的时候,就会发生活跃性问题。

具体问题和解决方法可见第十章:避免活跃性危险

3.3 性能问题

与活跃性问题关系密切的是性能问题。活跃性意义着某件正确的事情最终会发生,可是不够好,由于咱们一般但愿正确的事情尽快发生。

性能问题包括多方面:

  • 服务时间过长
  • 响应不灵敏
  • 吞吐率太低
  • 资源消耗太高
  • 可伸缩性较低

在设计良好的并发程序中,线程能提升程序的性能,可是不管如何,线程总会带来某种程度的运行开销。在多线程中,当线程调度器临时挂起活跃性线程并转而运行另外一个线程的时候,会频繁的出现上下文切换操做,带来很大的开销:保存和恢复执行上下文,丢失局部性,而且CPU时间将更多的花在线程调度而不是线程运行上。当线程共享数据时,必须使用同步机制,而这些机制每每会抑制某些编译器优化,使得内存缓存区中的数据无效,以及增长共享内存总线的同步流量。

具体问题和解决方法可见第十一章:性能与可伸缩性

3.4 线程无处不在

相关文章
相关标签/搜索