美文网首页
java多线程下,unlock报java.lang.Illega

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

作者: hongzhenw | 来源:发表于2022-05-23 20:53 被阅读0次

    测试代码

    若在代码里使用的是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.Illega

          本文链接:https://www.haomeiwen.com/subject/efhdprtx.html