类加载器
- 启动类加载器
- 扩展类加载器
- 应用程序类加载器
除了顶层的启动类加载器之外,其他的类加载器都应该有自己的父类加载器。。。 这就是类加载器的双亲委托模型。
工作流程:
- 类加载器收到类加载的请求。
- 委派给父类加载器完成。
- 最终传到顶层的启动类加载器。
- 当父类加载器在其范围内找不到该类就交给子类加载。
栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构。
栈帧是虚拟机运行时数据区中虚拟机栈的栈元素。
栈帧有 局部变量表,动态链接,方法返回地址,操作数栈 。
执行引擎只对位于栈顶的栈帧进行操作。
线程
线程安全程度:
- 不可变
最常见的就是前面加final - 绝对线程安全
- 相对线程安全
例如Vector等集合 - 线程兼容
指本身不是线程安全的,但是可以通过调用端正确使用手段来保证对象在并发环境中可以安全的使用。 - 线程对立
排斥多线程
线程安全的实现方法:
-
互斥同步
例如synchronized关键字。
互斥同步是一种悲观的并发策略。
认为只要不去做正确的事情例如加锁那么就会出现问题。
无论共享数据是否真的会出现竞争,都会加锁。 -
非阻塞同步
先进行操作,如果没有其他线程争用共享数据,那操作就成功了,如果共享数据有争用,产生了冲突,在不断的重试,一直到成功。 -
无同步方案
如果不涉及共享数据就不用进行任何同步操作。例如- 可重入代码。 如果一个方法,它的返回结果可以预测,只要输入相同的数据,就能产生相同的结果,就是线程安全的。
- 线程本地存储。 吧共享数据的可见范围控制在一个线程内。那么不用同步也可以保证线程之间的安全。
锁优化
- 自旋锁和自适应自旋
因为共享数据的锁定状态一般都很短,在这么短的时间去执行线程挂起和恢复并不划算,那么就让线程执行一个忙等待。如果自旋超过10次。那么这个线程就会被挂起,以此防止自旋时间过长。 - 锁消除
如果判断在这段代码中,堆上的数据都不会逃逸,被其他线程访问到,那么就可以把这些数据当成私有的,就不同加锁了。 - 锁粗化
如果有一串琐碎的操作都是对同一个对象进行重复加锁,那么就会吧这个锁的同步范围扩大到整个操作序列的外部。
锁
- 重量级锁
使用操作系统互斥量来实现同步。 - 轻量级锁
无竞争情况下, 多个线程交替使用锁。
轻量级锁只是为了减少传统的重量级锁锁产生的性能消耗,但是一旦出现同一时间访问同一锁的情况,就会膨胀为重量级锁。 - 偏向锁
无实际竞争,且将来只有第一个申请锁的线程会使用锁,只有第一次需要付出成本申请锁,往后都无需成本。但是如果有竞争,会膨胀为轻量级锁。