关于悲观锁&乐观锁、CAS以及线程池的解析与总结笔记
Java并发
乐观锁与悲观锁
现实生活中,有资源就有竞争,我认为锁就是对有限资源的一种争取;程序中的锁也是一样,对共享资源(内容)进行操作,需要保证操作的安全性,即保证共享资源的完整性和一致性。
- 乐观锁:认为共享资源每次访问的时候都不会出问题,不需要加锁,只需要在提交修改时再判断对应的资源是否符合预期(即在最终操作数据时做校验,而不是一上来就认为不行)。具体可以使用数据库版本号或CAS技术来实现。
- 悲观锁:认为共享资源每次访问时都会有问题,所以每次获取数据都需要加锁(独享),直到自己操作完成后释放锁之后,其他线程才可以进行操作。Java中的
synchronized
和ReentrantLock
等独占锁就是悲观锁思想的实现。
CAS
CAS(compare and swap)是一种乐观锁的实现方式,全称是"比较并交换",是Java中一种无锁的原子性操作。
CAS操作包含三个操作数——内存位置(V)、期望的原值(A)和新值(B)。
工作原理:当且仅当内存位置V的值等于预期原值A时,将该内存位置V的值替换为新值B。并且整个比较和更新操作都是原子操作。
无锁:指的是不通过锁机制对共享数据来实现线程安全
java.util.concurrent.atomic
包下提供了一系列原子类(e.g. AtomicInteger、AtomicLong),它们内部都使用CAS操作来保证线程安全。底层通过sun.misc.Unsafe#compareAndSetInt方法实现(注:该方法是native方法)。
或者说CAS机制其实是通过native boolean compareAndSetInt()
方法实现的,AtomicLong底层调用了该方法。
线程池
背景:当任务比较繁重,线程创建过多会带来调度开销,即线程的频繁创建与销毁,类似于TCP连接的频繁创建与销毁
线程池是一种线程使用模式,线程池中维护着多个线程,等待调度器分配可并发执行的任务,避免了在处理短时间任务时创建与销毁线程的代价。
特点/好处:
- 降低资源消耗:重复利用已创建的线程来避免频繁的线程创建和销毁造成的消耗
- 提高响应速度:当出现可执行任务时,不需要等待线程的创建,任务可以立马被执行
- 提高线程的可管理性:线程是稀缺资源,如果无节制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控