利用AQS实现可重入锁,执行单测报错

来源:11-7 利用AQS实现独占锁

冬天吃饺子

2020-09-10

package lock.lock;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * 自定义实现的可重入锁
 */
public class MyReentrantLock {

    private static int testNumber = 0;
    private Sync sync;

    public MyReentrantLock() {
        this.sync = new Sync();
    }

    public static void main(String[] args) throws Exception {
        MyReentrantLock myMutexLock = new MyReentrantLock();
        CountDownLatch countDownLatch = new CountDownLatch(2);
        new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                myMutexLock.lock();
                try {
                    testNumber++;
                } finally {
                    myMutexLock.unlock();
                }
            }
            countDownLatch.countDown();
        }).start();

        new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                myMutexLock.lock();
                try {
                    testNumber++;
                } finally {
                    myMutexLock.unlock();
                }
            }
            countDownLatch.countDown();
        }).start();

        countDownLatch.await();
        System.out.println(testNumber);
        assert testNumber == 20000;
    }

    public void lock() {
        sync.acquire(1);
    }

    public void unlock() {
        sync.release(1);
    }

    private class Sync extends AbstractQueuedSynchronizer {
        @Override
        protected boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        @Override
        protected boolean tryAcquire(int arg) {
            if (getState() == 0) {
                if (compareAndSetState(0, arg)) {
                    setExclusiveOwnerThread(Thread.currentThread());
                    return true;
                }
            } else if (isHeldExclusively()) {
                int c = getState() + arg;
                setState(c);
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            if(!isHeldExclusively()){
                throw new IllegalMonitorStateException();
            }
            int newState = getState() - arg;
            setState(newState);
            if (newState == 0) {
                setExclusiveOwnerThread(null);
                return true;
            } else {
                return false;
            }
        }
    }
}

这个是自定义实现的独占锁,发现一个问题,把setState方法放到setExclusiveOwnerThread方法前面,执行单测会报错。。。,我debug发现报错的时候,
exclusiveOwnerThread属性为空。悟空老师能帮忙看下么

写回答

1回答

悟空

2020-09-11

这个问题,你自己探索一下,调试一下,会更好,参考已有的JDK的锁代码哈,或者网上找一下自己实现的可重入锁。

0
4
冬天吃饺子
回复
悟空
我试了下,把ReentrantLock复制下来,然后修改了下tryRelease方法,调整了顺序,也是会报这个错误。。。。。
2020-09-11
共4条回复

深度解密Java并发工具,精通JUC,成为并发多面手

JUC全方位讲解,构建并发工具类知识体系

1599 学习 · 573 问题

查看课程