title: JUC.自定义非可重入独占锁
UnableReentrantLock提纲
## UnableReentrantLock简介
可重入锁,也叫做递归锁,指的是在同一线程内,外层函数获得锁之后,内层递归函数仍然可以获取到该锁。换一种说法:同一个线程再次进入同步代码时,可以使用自己已获取到的锁。
防止在同一线程中多次获取锁而导致死锁发生。
非可重入锁实现
首先看一下类结构图
通过Sync继承AQS实现非可重入锁,state只能为1再次获取的时候失败。下面看下具体的代码
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
/**
* @ClassName UnableReentrantLock
* @Description is a unable reentrant lock
* @Author Allen
* @Date 2018/11/21 22:15
* @Version
*/
public class UnableReentrantLock implements Lock, Serializable {
private static class Sync extends AbstractQueuedSynchronizer {
@Override
protected boolean isHeldExclusively() {
return getState() == 1;
}
@Override
public boolean tryAcquire(int acquires) {
assert acquires == 1;
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int releases) {
assert releases == 1;
if (getState() == 0) {
throw new IllegalMonitorStateException();
}
setExclusiveOwnerThread(null);
setState(0);
return true;
}
Condition newCondition() {
return new ConditionObject();
}
}
private final Sync sync = new Sync();
@Override
public void lock() {
sync.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return sync.tryAcquire(1);
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(time));
}
@Override
public void unlock() {
sync.release(0);
}
@Override
public Condition newCondition() {
return sync.newCondition();
}
}
测试死锁
要实现一个死锁其实是一件非常简单的事情,随便弄弄就死锁了。
1.互斥:某种资源一次只允许一个进程访问,即该资源一旦分配给某个进程,其他进程就不能再访问,直到该进程访问结束。
2.占有且等待:一个进程本身占有资源(一种或多种),同时还有资源未得到满足,正在等待其他进程释放该资源。
3.不可抢占:别人已经占有了某项资源,你不能因为自己也需要该资源,就去把别人的资源抢过来。
4.循环等待:存在一个进程链,使得每个进程都占有下一个进程所需的至少一种资源
实现上面规则即可触发条件召唤死锁。
看下我基于上面的非重入锁完美触发死锁的测试代码如下
/**
* @ClassName MyLockTest
* @Description test deadLock
* @Author Allen
* @Date 2018/11/21 11:01
* @Version
*/
public class MyLockTest {
private String lock;
private final UnableReentrantLock unableReentrantLock = new UnableReentrantLock();
public void printAndSetLock() {
unableReentrantLock.lock();
System.out.println(lock);
setLock("hello lock");
System.out.println("completed set lock:"+lock);
unableReentrantLock.unlock();
}
public void setLock(String lock) {
unableReentrantLock.lock();
this.lock = lock;
unableReentrantLock.unlock();
}
public static void main(String[] args) {
MyLockTest myLockTest = new MyLockTest();
myLockTest.printAndSetLock();
}
}
欢迎扫码加入知识星球继续讨论