java并发-14-可重入锁
| 分类: java |
1.
可重入锁是指能够重复进入的锁。例如一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接执行调用的方法,而无需重新获得锁。场景:数据库事务操作,add操作将会获取锁,若一个事务当中多次add,就应该允许该线程多次进入该临界区。
synchronized关键字和ReentryLock都是可重入锁。
2.
在以下程序中,子类改写了父类的synchronized 方法,然后调用父类中的方法,此时如果内置锁不是可重入的,那么这段代码将产生死锁。由于 Widget 和LoggingWidget中doSomething方法都是 synchronized 方法,因此每个doSomething方法在执行前都会获取 Widget 上的锁。然而如果内置锁不是可重入的,那么调用super.doSomething( )时无法获得 Widget 上的锁,因为这个锁已经被持有,从而线程将永远停顿下去,等待一个永远也无法获得的锁。重入则避免了这种死锁情况的发生。
http://s12/mw690/002i2qf8zy7jRxlSshteb&690
3.
ReentryLock重写了AQS中的tryAcquire和tryRelease方法。可以看到ReentryLock默认构造器是非公平锁,内部执行都利用了属性sync的sync.lock和sync.release(1)等方法,Sync类继承了AQS。每重入一次(当前线程是持有锁的线程),那么AQS(ReentryLock继承)的state就会加1,每释放一次锁,state就会减1。
具体的for(;;)自旋获取锁参见AQS中的acquire方法中的acquireQueued。
public class ReentrantLockimplements Lock, java.io.Serializable {
private static final long serialVersionUID= 7373984872572414699L;
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID= -5179523762034025860L;
abstract void lock();
final booleannonfairTryAcquire(intacquires) {
final Thread current = Thread.currentThread();
intc = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
intnextc = c + acquires;
if (nextc<</span>0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
protected final booleantryRelease(intreleases) {
intc = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException() ;
booleanfree = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
protected final booleanisHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
final ConditionObjectnewCondition() {
return new ConditionObject();
}
// Methods relayed from outer class
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
final intgetHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
final booleanisLocked() {
return getState() != 0;
}
private void readObject(
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(booleanfair) {
sync = fair ? new FairSync() : new NonfairSync();
}
public void lock() {
sync.lock();
}
publicbooleantryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
public void unlock() {
sync.release(1);
}
}
下面以非公平锁为例,介绍了具体实现方法。最终tryAcquire调用了sync中的nonfairTryAcquire方法,试图利用CAS方法改变AQS中当前节点状态,如果失败则按照acquire方法进行自旋或挂起。
static final class NonfairSyncextends Sync {
private static final long serialVersionUID= 7316153563782823691L;
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final booleantryAcquire(intacquires) {
return nonfairTryAcquire(acquires);
}
}
参考文献
[1] https://www.cnblogs.com/yutingliuyl/p/7352491.html
[2] https://www.cnblogs.com/yuyutianxia/p/4296220.html
[3]
https://juejin.im/post/5921927c44d904006cca9720
[4]https://www.zhihu.com/question/23284564

加载中…