多线程基础
多线程
进程和线程:进程是操作系统里的一块独立的区域,线程运行在进程内部,线程之间共享资源
cpu线程:cpu在硬件级别同时能做事情的数量
public ThreadPoolExecutor(int corePoolSize, //默认线程数,也就是线程池创建时自带线程数,回收后剩余的数也是这个
int maximumPoolSize,//最大线程数
long keepAliveTime,//线程等待时间,也就是闲置后多久被回收
TimeUnit unit,
BlockingQueue<Runnable> workQueue
) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
线程安全
volatile
保证了可见性和禁止指令重新排序
多线程访问同一个变量,会先把变量考到自己内存里,对其修改后再拷回去,这样效率很高,但会有线程安全问题
最大积极性同步,每次使用时拷一份最新的,每次修改后立刻拷回去
synchronize
原子操作:指不可分割的操作 i++不是,因为会分为 temp = i + 1; i = temp
多线程执行非原子操作(方法)时,可能在方法的中间发生线程切换,导致出现问题
synchronize 会为方法加一个monitor,这个会监视所有访问此方法的线程,如果此方法正被其他线程调度,motitor会拒绝访问,一个对象里默认所有方法共享一个monitor(指向this),为什么这么设计,因为不同的方法可能会访问同一个变量,可以为monitor指定对象:
synchronize(对象) {}
AtonmicInteger:对int的包装,增加原子性和同步性 .incrementAndGet()相当于++i且线程安全
静态方法monitor用静态对象,或xxx.class
单例的应用 双重null判断,单例对象加volatile,有时java创建对象还未万全准备好时就会把对象标记为可用
ReentrantLock
注意try finally中unlock处理,否则容易半途出现问题走不到unlook永远锁住
ReentrantReadWriteLock:可以分出读写锁,多线程可以一起读,但不能同时读写或同时写
死锁
多个锁被不同方法块使用,并且都需要对方正在使用的锁,程序会卡主
乐观锁与悲观锁
乐观,读数据的时候不上锁,修改完检查,如果数据未被改动,就上锁写入
悲观,从读数据开始一直到重新写入,一直上锁
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 炎武的学习笔记!