早期计算机->操作系统加入->线程与进程
早期计算机不包含操作系统,它们从头到尾只执行一个程序,并且这个程序能访问计算机所有资源。
加入操作系统主要是基于以下原因:资源利用率、公平性、便利性
操作系统使得计算机每次能运行多个程序,并且不同的程序在单独的进程中运行。在不同进程之间可以通过一些粗粒度的通信机制来交换数据,包括:套接字、信号处理器、共享内存、信号量以及文件等。
由于同一个进程中所有的线程都将共享进程的内存地址,因此这些进程都能访问相同的变量并且在同一个堆上分配对象,这就需要一张比在进程间共享数据粒度更细的数据共享机制。
线程也被称为轻量级进程。在大多数现代操作系统中,都是以线程为基本的调度单位,而不是进程。
线程允许在同一个进程中同时存在多个程序控制流。线程会共享进程范围内的资源,例如内存句柄和文件句柄,但每个线程都有各自的程序计数器、栈以及局部变量等。
线程优势/带来的问题
线程的优势:
1、发挥多处理器的强大能力
2、建模的简单性
3、异步事件的简化处理
4、响应更灵敏的用户界面
线程带来的风险
1、安全性问题
没有充分同步的情况下,多个线程的操作执行顺序是不可预测的,甚至会产生奇怪的结果。
线程安全性的例子:
package chapter1;
import common.NotThreadSafe;
/**
* @author zhen
* @Date 2018/10/10 10:25
*/
@NotThreadSafe
public class UnsafeSequence {
private int value;
/** 返回一个唯一的数值 */
public int getNext() {
return value++;
}
}
package chapter1;
import common.GuardedBy;
import common.ThreadSafe;
/**
* @author zhen
* @Date 2018/10/10 10:35
*/
@ThreadSafe
public class Sequence {
@GuardedBy("this") private int value;
public synchronized int getNext() {
return value++;
}
}
2、活跃性问题
某件正确的事情最终会发生。可能因为死锁等一直没有到来
3、性能问题
线程带来额外开销
线程无处不在
JVM
Timer
Servlet
RMI