跳转至

关于悲观锁&乐观锁、CAS以及线程池的解析与总结笔记

Java并发

乐观锁与悲观锁

现实生活中,有资源就有竞争,我认为锁就是对有限资源的一种争取;程序中的锁也是一样,对共享资源(内容)进行操作,需要保证操作的安全性,即保证共享资源的完整性和一致性。

  • 乐观锁:认为共享资源每次访问的时候都不会出问题,不需要加锁,只需要在提交修改时再判断对应的资源是否符合预期(即在最终操作数据时做校验,而不是一上来就认为不行)。具体可以使用数据库版本号或CAS技术来实现。
  • 悲观锁:认为共享资源每次访问时都会有问题,所以每次获取数据都需要加锁(独享),直到自己操作完成后释放锁之后,其他线程才可以进行操作。Java中的synchronizedReentrantLock等独占锁就是悲观锁思想的实现。

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连接的频繁创建与销毁

线程池是一种线程使用模式,线程池中维护着多个线程,等待调度器分配可并发执行的任务,避免了在处理短时间任务时创建与销毁线程的代价。

特点/好处:

  • 降低资源消耗:重复利用已创建的线程来避免频繁的线程创建和销毁造成的消耗
  • 提高响应速度:当出现可执行任务时,不需要等待线程的创建,任务可以立马被执行
  • 提高线程的可管理性:线程是稀缺资源,如果无节制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控