Lock实现原理
Lock完全用Java写成,在java这个层面是无关JVM实现的。
在java.util.concurrent.locks包中有很多Lock的实现类,常用的有ReentrantLock、ReadWriteLock(实现类ReentrantReadWriteLock),其实现都依赖java.util.concurrent.AbstractQueuedSynchronizer类,实现思路都大同小异,因此我们以ReentrantLock作为讲解切入点。
实现Lock接口的类有很多,以下为几个常见的锁实现
- ReentrantLock:表示重入锁,它是唯一一个实现了Lock接口的类。重入锁指的是线程在获得锁之后,再次获取该锁不需要阻塞,而是直接关联一次计数器增加重入次数
- ReentrantReadWriteLock:重入读写锁,它实现了ReadWriteLock接口,在这个类中维护了两个锁,一个是ReadLock,一个是WriteLock,他们都分别实现了Lock接口。读写锁是一种适合读多写少的场景下解决线程安全问题的工具,基本原则是:
读和读不互斥、读和写互斥、写和写互斥
。也就是说涉及到影响数据变化的操作都会存在互斥。 - StampedLock: stampedLock是JDK8引入的新的锁机制,可以简单认为是读写锁的一个改进版本,读写锁虽然通过分离读和写的功能使得读和读之间可以完全并发,但是读和写是有冲突的,如果大量的读线程存在,可能会引起写线程的饥饿。stampedLock是一种乐观的读策略,使得乐观锁完全不会阻塞写线程
JUC的atomic包下运用了CAS的AtomicBoolean、AtomicInteger、AtomicReference等原子变量类
JUC的locks包下的AbstractQueuedSynchronizer(AQS)以及使用AQS的ReentantLock(显式锁)、ReentrantReadWriteLock
附:运用了AQS的类还有:Semaphore、CountDownLatch、ReentantLock(显式锁)、ReentrantReadWriteLock
JUC下的一些同步工具类:CountDownLatch(闭锁)、Semaphore(信号量)、CyclicBarrier(栅栏)、FutureTask
JUC下的一些并发容器类:ConcurrentHashMap、CopyOnWriteArrayList
JUC下的一些Executor框架的相关类: 线程池的工厂类->Executors 线程池的实现类->ThreadPoolExecutor/ForkJoinPool
JUC下的一些阻塞队列实现类:ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue