- 多线程基础概念:
- 进程和线程的区别:进程用于把所需资源集中到一起,而线程则是在CPU上被调度执行的实体。
- 操作系统中的进程与线程
- 创建新线程
- 继承Thread,调用start()启动
- 实现Runnable,调用new Thread(Runnable).start()启动
- 使用线程池,提交任务执行,例如:Executors.newSingleThreadExecutor().submit(Callable)
- 线程的状态:
- New:新创建的线程,尚未执行;
- Runnable:运行中的线程,正在执行run()方法的Java代码;
- Blocked:运行中的线程,因为某些操作被阻塞而挂起;
- Waiting:运行中的线程,因为某些操作在等待中;
- Timed Waiting:运行中的线程,因为执行sleep()方法正在计时等待;
- Terminated:线程已终止,因为run()方法执行完毕。
- 线程同步synchronized
- 修饰static方法:对Class对象加锁
- 修饰非static方法:对Class的实例对象加锁
- synchronized(obj){ }代码块:锁定指定对象
- synchronized实现原理:
- 字节码实现:
- synchronized代码块通过monitorenter和monitorexit指令实现
- 方法上的synchronized通过ACC_SYNCHRONIZED标志告诉jvm来支持
- 底层实现:
- 被锁定对象头中的markword中保存了对象上的锁的信息:JDK6之前只有两个状态:无锁、有锁(重量级锁),JDK6之后进行了优化,总共就是四个状态:无锁状态、偏向锁、轻量级锁、重量级锁。
- 每一个对象锁在JVM中都有一个对应的monitor(管程)对象
- 锁膨胀升级过程:无锁——>偏向锁——>轻量级锁——>重量级锁,方向不可逆
- 当线程首次获取锁时,从无锁转为偏向锁,记录当前线程id,当前线程重新申请锁时不需要竞争
- 当第二个线程申请锁时,会将锁升级到轻量级锁,线程之间交替获得锁,线程通过轮询申请锁,不会进行上下文切换
- 当等待申请锁的线程很多时,轻量级锁会升级到重量级锁,此时线程申请锁时都会进行上下文切换
- 锁优化:锁升级,锁消除,锁粗化,自旋锁与自适应自旋锁
- 锁升级:无锁——>偏向锁——>轻量级锁——>重量级锁
- 锁消除:通过对运行上下文的扫描,去除不可能存在共享资源竞争的锁,通过这种方式消除没有必要的锁
- 锁粗化:通过扩大锁的范围,避免反复加锁和释放锁
- 自旋锁:轻量级锁线程申请锁失败后,不会立马再次申请,而是自旋一定次数后再申请,成功率更高;
- 自适应自旋锁:自旋次数不固定,自旋次数由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定
- 字节码实现:
- CAS与Atomic类
- CAS:Compare And Swap,是操作系统底层支持的一种原子指令,可以用来实现无锁操作
- CAS相关功能来自Unsafe类中的对应native方法
- CAS的缺点,ABA问题,CPU浪费问题
- Java中的Atomic类就是运用了CAS的机制
- Atomic类列表:
- AtomicBoolean,
- AtomicInteger, AtomicIntegerArray, AtomicIntegerFieldUpdater,
- AtomicLong, AtomicLongArray, AtomicLongFieldUpdater, AtomicMarkableReference,
- AtomicReference, AtomicReferenceArray, AtomicReferenceFieldUpdater, AtomicStampedReference,
- DoubleAccumulator, DoubleAdder, LongAccumulator, LongAdder,
- Atomic类列表:
- CAS:Compare And Swap,是操作系统底层支持的一种原子指令,可以用来实现无锁操作
- 锁工具类与AQS
- Java中常用的显示锁相关类:ReentrantLock(Condition等待队列), ReentrantReadWriteLock, StampedLock(改进的读写锁), LockSupport,
- 同步器: Semaphore(信号), CountDownLatch(门闩), CyclicBarrier(循环栅栏), Exchanger(交换器), Phaser(阶段),
- AbstractQueuedSynchronizer是用来构建锁或者其他同步组件的基础框架,它使用了一个 int 成员变量表示同步状态,通过内置的 FIFO 队列来完成资源获取线程的排队工作。
- 线程池
- 线程池:ThreadPoolExecutor, ScheduledThreadPoolExecutor, ForkJoinPool
-
工具:Executors
- 同步容器
参考:
synchronized底层原理
AQS源码解析