AQS实现非可重入锁


title: JUC.自定义非可重入独占锁

UnableReentrantLock提纲

## UnableReentrantLock简介

可重入锁,也叫做递归锁,指的是在同一线程内,外层函数获得锁之后,内层递归函数仍然可以获取到该锁。换一种说法:同一个线程再次进入同步代码时,可以使用自己已获取到的锁。
防止在同一线程中多次获取锁而导致死锁发生。

非可重入锁实现

首先看一下类结构图
avatar
通过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();
    }
}

欢迎扫码加入知识星球继续讨论
avatar

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值