ReentrantLock.lock();
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReentrantLock.lock();相关的知识,希望对你有一定的参考价值。
reentrantlock对象,里面有一个state属性,volatile的,对其进行cas操作,可以作为锁使用。
ReentrantLock lock = new ReentrantLock();
lock.lock();方法调用的是sync.lock()方法,sync是ReentrantLock的全局变量名,如果调用无参构造函数,生成的是一个非公平的lock,调用带参数可以确定是公平锁还是非公平。
非公平锁,的lock方法,调用的是,
final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); }
逻辑是,把state变量,也就是那个锁,置换成1的状态,加锁,如果成功了,就把lock对象当前的锁定线程赋值为当前线程。
如果没成功,说明现在是加锁的,那么执行acqire()方法
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
逻辑是,先执行tryAcquire方法
protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } 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; }
就是先试着再去加锁一次,如果还没成功,再检测加锁的是否是当前线程,如果是的话,那么重入,把state值加一
如果以上都不成功,那么返回false
接下来看acquireQueued方法
final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC failed = false; return interrupted; } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } }
这个是AbstractQueuedSynchronizer抽象类的方法,给Sync继承,
private Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } enq(node); return node; }
先看addwaiter方法,在Sync对象的尾部(lock对象其实只是对sync对象的封装,sync才是真正的锁,sync对象内部除了一个volatile的锁state,还有两个node节点(node节点内部有一个前驱指针,一个后续指针,一个存线程引用的变量),一个指向头(头内部没有有用数据),一个指向尾部tail,保留一个等待这个锁的线程队列,
在这里实现公平非公平,addwaiter方法,就是把当前没有获取到锁的线程,做成一个node封装起来,放在队列最后,并返回这个node。
acquireQueued方法,有空再看
以上是关于ReentrantLock.lock();的主要内容,如果未能解决你的问题,请参考以下文章
深入显出一篇能懂Java锁机制,Synchronized和ReentrantLock