最新消息:vps推荐

java中锁概念理解:可重入锁、可中断锁、公平锁

java Terry 383浏览 0评论

1、可重入锁

可重复递归调用的锁,在外层获得锁后内层可以直接使用(同一对象)就叫可重入锁。synchronized和ReentrantLock都是可重入锁。

synchronized实例:

public class LockTest {
    private synchronized void get(){
        System.out.println("get test");
        set();
    }

    private synchronized void set(){
        System.out.println("set test");
    }

    public static void main(String[] args) {
        LockTest lockTest = new LockTest();
        lockTest.get();
    }
}

输出结果为:

get test
set test

假如synchronized不具有可重入性,主线程在执行get方法时获取到了锁,内部执行set方法又去获取锁,此时并没有释放锁因此也就获取不到锁就会死锁。synchronized具备可重入性就避免死锁的发生。

下面看看ReentrantLock可重入性的实现:

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;
        }

在多次去获取锁时,通过getExclusiveOwnerThread()获取当前占有锁的线程,如果和当前线程一致则计数器加一并返回true。

2、可中断锁

可以响应中断的锁就是可中断锁。synchronized不是可中断锁,而Lock是可中断锁。

如果a线程长期占有锁,b线程等待一段时间后不想等待了就可以通过Lock接口的tryLock(long time, TimeUnit unit)和lockInterruptibly()方式中断等待去干别的事。而synchronized则需要一致等待下去。

3、公平锁

synchronized是非公平锁。ReentrantLock和ReentrantReadWriteLock默认情况下是非公平的,可以通过设置为公平锁。公平锁就是尽量以请求锁的顺序来获取锁。

ReentrantLock公平锁实例:

public class LockTest {
    private ReentrantLock fairLock = new ReentrantLock(true);

    private void print(){
        try {
            fairLock.lock();
            System.out.println("线程:"+Thread.currentThread().getName()+"获取锁");
        } finally {
            System.out.println("线程:"+Thread.currentThread().getName()+"释放锁");
            fairLock.unlock();
        }
    }

    public static void main(String[] args) {
        LockTest lockTest = new LockTest();
        for(int i=0;i<10;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    lockTest.print();
                }
            }).start();
        }
    }
}

输出结果:

线程:Thread-0获取锁
线程:Thread-0释放锁
线程:Thread-2获取锁
线程:Thread-2释放锁
线程:Thread-4获取锁
线程:Thread-4释放锁
线程:Thread-6获取锁
线程:Thread-6释放锁
线程:Thread-8获取锁
线程:Thread-8释放锁
线程:Thread-1获取锁
线程:Thread-1释放锁
线程:Thread-5获取锁
线程:Thread-5释放锁
线程:Thread-3获取锁
线程:Thread-3释放锁
线程:Thread-9获取锁
线程:Thread-9释放锁
线程:Thread-7获取锁
线程:Thread-7释放锁

可以看到只是尽量保持公平

 

转载请注明:Terry's blog » java中锁概念理解:可重入锁、可中断锁、公平锁

发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址