线程的状态/线程的生命周期
- 初始化
Thread thread = new Thread();
- 运行
thread.start();
- 运行中状态 ——> 调用
yeild
进入就绪状态 - 就绪状态 ——> 通过系统调度(
获取到cpu时间片
),又会进入到运行中状态
- 运行中状态 ——> 调用
- 等待
调用如下方法就从运行进入到等待状态:
Object.wait()、Object.join()
、LockSupport.park();
在调用如下方法后,又会从等待状态进入到运行状态:
Object.notify()/notifyAll()
、LockSupport.unpark(thread) - 等待超时
调用如下几个方法执行时间超时后就会进入到运行状态:
Object.wait(1000)、Object.join(1000)、Thread.sleep(1000)、
LockSupport.parkNanos()、 LockSupport.parkUntil(); - 阻塞
多个线程等待获取到synchronized
同步锁,此时这些等待的线程就是阻塞状态,获取到锁后就会从阻塞状态进入到运行中状态 - 终止
线程执行完成
死锁产生的必要条件(需要同时满足)
- 多个操作者争夺多个资源
- 争夺资源的顺序不对
- 拿到资源不放手
- 互斥
- 请求和保持
- 不剥夺
- 环路等待
如何打破死锁?
- 申请足够的资源
- 保证争夺资源的顺序正确,让多个线程同时去竞争同一个资源
- 通过Lock的tryLock和unLock方法去操作,活锁去执行.
CAS (Compare And Swap)
什么是原子操作?
要么全部完成,要么全部都不做,不可再分
如何实现原子操作?
使用锁
CAS原理
利用了现代处理器都支持的CAS指令,循环这个操作,直至成功为止
CAS的问题
ABA问题
(在结果相同的情况下中间可能有做过别的操作,可以通过版本戳来解决)开销问题
(不停的循环会造成cpu开销问题,可以改用加锁机制解决)只能保证一个共享变量的原子操作
(使用范围比较局限,可以将多个变量构造成一个对象来处理)
CAS的使用
AtomicBoolean、AtomicInteger、AtomicLong
等等