可重入锁ReentrantLock和可重入读写锁ReentrantReadWriteLock

ReentrantLock和synchronized都是可重入锁,可重入锁的意思是:拥有锁的代码块中可以继续去获取锁。

    public synchronized void out(){//锁的是this对象,但是看不到锁
        //doSomething
        in();
    }
    public synchronized void in(){
        //doSomething
    }


    public void out() {
        //doSomething
        ReentrantLock lock = new ReentrantLock();//默认是非公平锁,性能好
        try {
            lock.lock();//不允许Thread.interrupt中断,即使检测到Thread.isInterrupted,一样会继续尝试获取锁,失败则继续休眠。
            in();
        } finally {
            lock.unlock();//手动释放锁,否则发生异常的话锁就永远都释放不了了
        }
    }

    public void in() {
        ReentrantLock lock = new ReentrantLock(true);//这个是公平锁,性能差
        try {
            lock.lockInterruptibly();//等待锁的时候,可以被Thread.interrupted()中断,并抛出异常
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

说一下ReentrantLock和synchronized的区别:

1、ReentrantLock可以实现公平锁(先申请锁的先得到锁),synchronized不行。

2、ReentrantLock需要手动释放锁(在finally块,否则可能会造成死锁),synchronized不需要。

3、ReentrantLock等待锁的时候可被中断,synchronized不可以。

4、ReentrantLock可以尝试获得锁,lock.tryLock(),有锁返回true,没锁返回false,synchronized不可以。

5、ReentrantLock上锁的是condition对象,synchronized上锁的是Object对象。

6、ReentrantLock类可以唤醒指定条件的线程,而object的唤醒是随机的。(因为同一个锁可以生成多个condition)

7、ReentrantLock锁的粒度更细,功能更多,性能也较好。

ReentrantLock的使用:

1、await()的使用,相当于Object的wait():

    ReentrantLock lock = new ReentrantLock();
    Condition condition=lock.newCondition();
    lock.lock();
    while(条件不满足)
         condition.await();

2、signal()和signalAll(),相当于Obejct的notify()和notifyAll()

3、常用方法:(3个get、3个has、3个is)

getHoldCount() :查询当前线程执行lock方法的次数

getQueueLength():返回正等待获取此锁的线程估计数

getWaitQueueLength(condition):执行了condition对象的await方法的线程数量 

hasWaiters(condition)、hasQueuedThread(thread)、hasQueuedThreads():查询是否有等待的线程、条件

isFair()、isHeldByCurrentThread()、isLock():是否公平、当前线程是否持有锁、锁是否被占用 

可重入读写锁ReentrantReadWriteLock

ReentrantLock是完全互斥排他的,这样其实效率是不高的。因此有了读写锁:读读共享,写写互斥,读写互斥

ReentrantReadWriteLock lock1 = new ReentrantReadWriteLock();
ReentrantReadWriteLock.ReadLock readLock = lock1.readLock();//同一时刻可以有多个读锁
ReentrantReadWriteLock.WriteLock writeLock = lock1.writeLock();//同一时刻,只能有一个写锁

获取写锁的,需要等到读锁都释放了才能获取到。

参考博客:

https://blog.csdn.net/yyd19921214/article/details/49737061

https://blog.csdn.net/zxd8080666/article/details/83214089

https://www.cnblogs.com/-new/p/7256297.html

觉得有用的老铁们赞一下呗,谢谢!

发布了78 篇原创文章 · 获赞 131 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/river66/article/details/91870149