ReentrantLock
可重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的。在释放的时候,也需要相应的释放n次
synchronized 和 ReentrantLock 都是可重入锁。
可重入锁的意义之一在于防止死锁。
构造方法如图所示:默认实现的是非公平锁
基本使用
new Thread(){ @Override public void run() { super.run(); //state 由0->1 至此同一线程的锁变成无锁状态 reentrantLock.lock(); System.out.println(Thread.currentThread().getId()); set(); //state 由1->0 至此同一线程的锁变成无锁状态 reentrantLock.unlock(); } }.start(); public static void set() { //第二个断点打在这 state 1->2 reentrantLock.lock(); System.out.println(Thread.currentThread().getId()); //2->1 reentrantLock.unlock(); }
第一次 state=0 if成立
setExclusiveOwnerThread将当前线程和这把锁进行绑定,防止其他线程占有
进入set方法 也就是第二个lock,很显然这里就不是0了 所以走else
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } //这里为啥进入了非公平锁的获取是因为在构造ReentranLock时如果是空构造函数, //就是非公平锁 后面会将公平锁和非公平锁的底层原理 protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } ///来到了ReentrantLock的nonfairTryAcquire具体实现方法 先获取state 还是先比较state是不是0 如果不是 就比较当前线程是不是绑定的线程 //是的话state+1 final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库