java多线程下,unlock报java.lang.IllegalMonitorStateException

测试代码

若在代码里使用的是tryLock和unlock

private Lock mLock = new ReentrantLock();

public void demo() {
    for (int i = 0; i < 10; i++) {
        final int finalI = i;
        new Thread(new Runnable() {
            @Override
            public void run() {
                test(finalI);
            }
        }).start();
    }
}

public void test(int index) {
    try {
        if (!mLock.tryLock()) {
            System.err.println(index + " locked:" + Thread.currentThread().getName());
            return;
        }
        // 伪代码 开始
        System.err.println(index + " run code");
        // 伪代码 结束
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        mLock.unlock();
        System.err.println(index + " unlock:" + Thread.currentThread().getName());
    }
}

多线程下,以上代码会报以下错误信息:

java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:156)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1291)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:466)

解决方案1

把tryLock方法放在try代码块外,理由:若获取不到锁,则会return,不再执行finally里的unlcok(测试代码则会,因为try代码块执行了)

修复代码如下:

public void test(int index) {
    if (!mLock.tryLock()) {
        System.err.println(index + " locked:" + Thread.currentThread().getName());
        return;
    }
    try {
        // 伪代码 开始
        System.err.println(index + " run code");
        // 伪代码 结束
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        mLock.unlock();
        System.err.println(index + " unlock:" + Thread.currentThread().getName());
    }
}

输出结果如下:

0 run code
0 unlock:Thread-3
1 run code
1 unlock:Thread-4
2 locked:Thread-5
3 locked:Thread-6
4 locked:Thread-7
5 locked:Thread-8
6 locked:Thread-9
7 locked:Thread-10
8 locked:Thread-11
9 locked:Thread-12

解决方案2

把Lock改为ReentrantLock,以及配合isHeldByCurrentThread方法

修复代码如下:

public void test(int index) {
    try {
        if (!mLock.tryLock()) {
            System.err.println(index + " locked:" + Thread.currentThread().getName());
            return;
        }
        // 伪代码 开始
        System.err.println(index + " run code");
        // 伪代码 结束
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (mLock.isHeldByCurrentThread()) {
            mLock.unlock();
            System.err.println(index + " unlock:" + Thread.currentThread().getName());
        }
    }
}

输出结果如下:

0 run code
0 unlock:Thread-3
1 locked:Thread-4
2 locked:Thread-5
3 locked:Thread-6
4 locked:Thread-7
5 locked:Thread-8
6 locked:Thread-9
7 locked:Thread-10
8 locked:Thread-11
9 locked:Thread-12

你可能感兴趣的:(java多线程下,unlock报java.lang.IllegalMonitorStateException)