一切的源头在于榨取cpu,因为cpu跑的比内存快;执行一条指令,取决于内存存取的速度。于是在cpu和主存之间加了一块高速缓存cache,cpu执行在cache之间执行,执行完写回主存。
线程
进程:资源调度的基本单位
线程:cpu执行的基本单位
java锁
cpu内核数和线程数的关系?
一个内核对应一个线程,后来有超线程技术,可以模拟出多个
cpu时间片轮转机制 又叫RR,可以有多个,但有限制。 代价上下文切换消耗性能
常见方法介绍
位于Thread类的
废弃 导致资源得不到正常释放stop()interrupt()中断线程 不会立即停止,只是打了一个终端标志,线程可不理会。可配合isInterrupted()使用interrupted()判断是否中断并清空标志位,且是静态方法;isInterrupted()判断是否中断
使用boolean变量去关闭线程,,,可能会不及时 因为遇到sleep,wait
抛出中断异常,所以使用中断来关闭线程推荐
yield()当前线程让出cpu执行权,进入就绪状态;极有可能还是选中自己;不会让锁sleep()不会让锁join()a线程 执行b.join() a要等b执行完才执行 可让线程先后执行setDaemon()设置为守护线程;守护线程在所有非守护线程结束后自动结束;并且守护线程中的finlly不一定执行
线程调度方式:
- 协作式:一个线程执行完,通知下一个线程执行
- 抢占式:由系统分配执行时间,线程切换不由线程决定
锁
用来保证线程之间安全执行;前提是多个线程之间存在共享变量的访问;如果多线程之间没有共享变量的访问,不管是同步还是串行都没有安全问题;
synchronized
synchronized 就是语言特性 隐式锁
一般来说,都算重量级锁。jdk1.6后有了各种锁优化,性能还好。
原理:synchronized代码块或者方法,编译后会添加监视器进入和监视器结束指令。。。。来获取对象的监视器
对象锁
每个锁对象都有2个队列,一个就绪,一个阻塞;一个线程被唤醒会进入就绪;反之一个线程被wait就会进入阻塞;
- 同步块 锁普通变量 锁静态变量 锁this:锁对象实例
- 同步方法 普通方法:锁对象实例 静态方法:锁类对象
lock
Lock 是接口
具体实现有:ReentrantLock、ReadLock、WriteLock
一种显式锁,手动申请锁 释放锁;
显示锁标准范式:
lock.lock();
try{
// dddd
}finally{
lock.unlock();
}
常见锁概念
公平锁&非公平锁
一种分类;获取锁的时候是不是按照先来后到的原则,是就是公平锁,否则不是
可重入锁&不可重入锁
一种分类;对于同一个线程,可以重复获得同一把锁;synchronized是可重入锁
重量级锁&轻量级锁
一种分类;相对而言,synchronized偏重量级,轻量级锁有volatile,。。。。
乐观锁&悲观锁
一种分类;乐观锁就是每次都觉得没有人跟自己抢锁,直接操作。悲观锁,总有线程跟我抢,每次都去抢锁
显示锁&非显示锁
一种分类;显示锁就是手动申请锁 释放锁;与之不同的就是synchronized
独占锁&共享锁
读写锁,读共享 写独占 读写互斥
虚拟机锁优化
针对一些特殊的情况,采取一定的手段降低性能消耗
自旋锁
为了降低线程阻塞(阻塞就会挂起和唤醒线程,会转入内核态完成)的压力;并且部分共享数据的锁定状态持续很短的时间,这时阻塞就会不值得。让线程等待,采取一个忙循环;看持有锁的线程是否很快释放;如果超过一定次数(默认10),会用传统的方式挂起线程;
1.6默认开启,并引入自适应自旋;
锁消除
即时编译阶段,虚拟机行为;
虚拟机通过逃逸分析,去除不可能存在共享资源竞争的锁;比如stringbuffer在append时,每个applend都加了synchronized,当用在局部变量时,虚拟机会将锁退化掉
偏向锁 线程第一次获取锁,没有其他线程获取锁,该线程第二次获取跳过获取锁。如果有其他线程获取就会升级为重量锁
锁粗化
对于连续加锁同一个对象的代码,可以放大加锁范围,使加一次锁,避免频繁获取锁、释放锁所带来的的性能消耗
volatile 可见性 禁止重排序 不保证原子性 一写多读
threadlocal spring的事务(把数据连接存进去)
thread的一个成员变量ThreadLocal.ThreadLocalMap,每一个threadlocal作为key放进map中 threadlocal弱引用
最佳实践 在使用后 在删除掉;不能保存共享的变量,比如static修饰的变量
阻塞同步
通过线程阻塞和唤醒的同步
非阻塞同步
先进行操作,如果没有其他线程争用共享数据,则操作成功;反之,有了冲突,采用其他补偿措施。
异常释放锁
cas (compare and swap)比较交换
需要处理器指令支持cas指令 保证比较交换是原子性
保存(内存地址,旧值,)
ABA问题:带版本号解决
Lock 与 synchronized 区别?
synchronized 关键字 lock 接口对象 消耗不一样
synchronized 非公平 lock 都有
AQS
设计模式:模板方法
lock 使用的AQS
线程通信
等待/通知机制
常见方法介绍
位于Object类的
wait()
当前线程获取到锁之后,该方法使当前线程等待,执行后立即释放锁,直到其他线程通知这个锁对象上等待的线程。
当其他线程执行通知后,这个锁对象上等待的线程需要重新获取这个锁,获取到锁的线程在wait()方法后可继续执行;
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
wait(timeout)
当timeout=0,相当于wait();同wait(),不同的是在超时时间过后,会自动移出等待队列,然后竞争获得锁以得到执行;
notify() & notifyAll()
通知对象锁上等待的其他线程;执行后不立即释放锁;区别是notify()只通知一个;notifyAll()通知所有的
synchronized (obj) {
obj.notify();
... // Perform action appropriate to condition
}
共享变量
通过轮询这个变量,取决于轮询的间隔,会消费性能或者响应不及时。