在并发编程中,经常会遇到多个线程访问同一个共享资源,这时候我们要保证数据的一致性,那么就要用到了锁的概念,给资源加上锁,拿到锁所有权的人才能够进行操作共享资源,没有拿到锁的线程需要等待,等锁的所有权放开。
Java中实现锁的工具类有: synchronized和JDK以后才引用Lock接口锁 如:ReentrantLock(可重入锁),ReadWriteLock (读写锁) reentrantReadWriteLock (可以选择获取什么锁)
p.s jdk所在的jar路径是:java.util.concurrent.locks.lock
锁的分类:
根据锁的一些特性我们可以分为以下几种锁:
- 按照锁的执行顺序分类:公平锁,非公平锁
- 公平锁:多线程按照申请锁的顺序来获取锁
- 非公平锁:不按照线程申请的顺序来获取锁,比如:按照线程优先级等
e.g:ReentrantLock 可以指定是公平锁还是非公平锁 默认是非公平锁:但是构造函数中false则是就是公平锁
synchronized是非公平锁
p.s: Lock lock = new ReentrantLock(false) 公平锁
- 按照锁的可以同时被拥有的次数分类:独享锁,共享锁
- 独享锁:该锁一次只能被一个线程有用
- 共享锁:该锁一次可以被多个线程拥有
e.g java中独享锁:ReentrantLock和synchronized ,ReadWriteLock的写锁
java中的共享锁:ReentrantReadWriteLock ,ReadWriteLock的读锁
- 互斥锁和读写锁是独享锁的共享锁的实现
- 按照看待并发的同步态度,我们可以将锁分为悲观锁和乐观锁
- 悲观锁:并发对于同一数据的操作,一定会发生改变,不加锁一定会出现问题
- 乐观锁:并发对于同一数据的操作是不会发生修改的,更新结果的时候进行阐释,采用CAS算法,不加锁没有问题
e.g CAS算法compare and swap 比较并替换 是一种实时并发算法,就是更新值的时候,内存地址V中的值与预期的值是否一致,一致就更新,不一致,则取内存中的新值进行重新计算、
- 根据锁的应用理念我们设计一种新锁:分段锁
- 分段锁:对于一个操作对象,我们分段进行加锁,操作前确定操作的是哪一段,然后加锁,没有枷锁的部分还可以被别的线程正常访问
P.s:ConcurrentHashMap的实现就是分段锁
- 按照锁的作用场景:对象所,类锁,方法锁,代码段锁