锁分析 Lock
锁分析 Lock NonReentrantLock ReadLock 共享锁 ReentrantLock 重入锁 排他锁 sync.lock 返回值为void,表示如无异常发生都认为锁获取成功 FairSync.lock 公平锁 FairSync.tryAcquire 获取线程 获取线程重入次数 重入次数为0 是 也就是第一次获取锁 在队列头部(队列为空或者当前线程在队列头部) 获取锁 设置锁状态 重入次数 设置锁的独占线程 获取锁成功 否 当前线程是否是锁的独占线程 是 重入次数+1 成功获取锁 否 获取锁失败 NonfairSync.lock 非公平锁 NonfairSync.lock 按照假设当前线程是第一次获取锁来申请锁 成功 设置当前线程为锁的独占线程 失败 按照重入的方式获取锁 WriteLock 排他锁 CAS 存在ABA的问题 ReentrantLock 重入锁默认构造是非公平锁实现,当申请锁的线程刚好碰到正在执行的线程释放了锁,那么他就有机会直接获取到锁,而不用排队。 重入锁的公平锁实现原理: 如果当前线程第一次获取锁,如果当前线程在抽象队列同步执行器的队首位置,利用CAS原理修改线程重入次数为1,成功则修改锁的独占线程为当前线程。 如果当前线程不是第一次获取锁,那么判断当前锁的独占线程与当前获取锁的线程是否一致,如果一致那么获取锁成功。 重入锁的非公平锁实现原理: 尝试按照第一次获取锁的方式直接获取锁,成功则获取锁成功 失败则重入的方式获取锁(判断当前线程与锁的独占锁是否一致)
Lock本地锁应用场景
根据锁创建的位置可以分为,对象锁,全局锁
1、对象锁,对象持有锁,在并发访问对象资源时可以用该锁控制。
public class ObjectLock { private Lock objectLock = new ReentrantLock(); void objectLock(Ticket ticket) { objectLock.lock(); try { System.out.println(Thread.currentThread().getName()+":"+ticket.getNum()); ticket.setNum(ticket.getNum()+1); Thread.sleep(1000); } catch (Exception e) { Console.error(e); } finally { objectLock.unlock(); } } }
2、全局锁,创建一个静态常量的锁,在系统全局都可以使用该锁。
public interface LockConstant { Lock lock = new ReentrantLock(); }
void lockConstant(Ticket ticket) { Lock lock = LockConstant.lock; lock.lock(); try { System.out.println(Thread.currentThread().getName()+":"+ticket.getNum()); ticket.setNum(ticket.getNum()+1); Thread.sleep(100); } catch (Exception e) { Console.error(e); } finally { lock.unlock(); } }