Java"锁"事之五

可重入锁 VS 非可重入锁

  • 可重入锁:

又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。
Java中ReentrantLock和synchronized都是可以重入锁,可重入锁的一个优点是可一定程度避免死锁。

    public class Widget {
        public synchronized void doSomething() {
            System.out.println("方法1执行...");
        }
        
        public synchronized void doOthers() {
            System.out.println("方法2执行...");
        }
    }

上面代码中:类中的两个方法都是被内置锁synchronized修饰的,doSomething()方法中调用doOthers()方法。因为内置锁是可以重入的,所以同一个线程在调用doOthers()时可以直接获得当前对象的锁,进入doOthers()进行操作。
如果一个不可重入锁,那么当前线程在调用doOthers()之前需要将执行doSomething()时获取当前对象的锁释放掉,实际上该对象锁已被当前线程所持有,且无法释放。所以此时会出现死锁。

        /**
         * Performs non-fair tryLock.  tryAcquire is implemented in
         * subclasses, but both need nonfair try for trylock method.
         */
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

获取锁时先判断,如果当前线程就是已经占有锁的线程,则status值+1,并返回true。
释放锁时也是先判断当前线程是否是已占有锁的线程,然后再判断status,如果status等于0,才真正的释放锁

  • 非可重入锁:
    protected boolean tryAcquire(int acquires) {
        if (this.compareAndSetState(0, 1)) {
            this.owner = Thread.currentThread();
            return true;
        } else {
            return false;
        }
    }

    protected boolean tryRelease(int releases) {
        if (Thread.currentThread() != this.owner) {
            throw new IllegalMonitorStateException();
        } else {
            this.owner = null;
            this.setState(0);
            return true;
        }
    }

非重入锁尝试直接获取锁。
释放锁时也是直接将status置为0.


【基本功】不可不说的Java“锁”事

你可能感兴趣的:(Java"锁"事之五)