什么是显示锁?
显示锁,在Java开发中,是由程序可控的,例如lock方法,在调用lock方法之前,可以尝试调用tryLock来判断是否可以拿到锁,如果可以拿到锁,那么进行获取锁时执行的业务否则可以去执行其他不需要锁去执行的业务,在tryLock时可以指定等待超时时间,例如尝试拿锁超时了,可以直接调用lock无限时等待下去或者抛出异常。
什么是内置锁?
内置锁,是由Java内部来调节锁的获取与释放,而显示锁需要手动获取与手动释放。在可重入方面,内置锁自己可以解决重入次数,而显示锁,每次重入后必须要执行释放锁,否则会造成自己把自己锁死。
内置锁与显示锁的选择
1、根据业务场景,如果业务耗时短、一定会执行的情况,可以优先使用内置锁。当业务根据锁竞争情况选择性执行时或业务中在获取锁失败时,优先执行其他业务时,可以考虑显示锁。
2、性能方面。由于内置锁是Java内部提供的关键字,在jdk1.8之后,synchronized开发团队对该内置锁进行了大量优化,从性能上比显示锁要好,另外显示锁他是一个类,每次使用时,都需要new一个对象来,所以资源消耗上,显示锁的开资明显要高得多。
3、内置锁是不可控,显示锁是可控的。
4、默认情况下,内置锁和显示锁都使用的非公平锁。但显示锁可以在new 的时候指定选择公平/非公平锁。
Lock与ReentrantLock
Lock是一个接口,ReentrantLock是重入锁,是对Lock实现的。基本方法由lock、tryLock、tryLock带超时时间和时间单位TimeUnit、unlock、newCondition等基本方法。
ReadWriteLock与ReentrantReadWriteLock
ReadWriteLock是一个接口,ReentrantReadWriteLock是读写锁,是对ReadWriteLock的实现。
ReadWriteLock中包含了两个Lock接口readLock(读锁)、writeLock(写锁)。
读锁与写锁的关系
读锁,同一时间支持多个线程同时读取。
写锁,同一时间,只有一个线程可以写。
读锁与写锁互斥,在读的时候,不允许写,在写的时候,不允许读。使用与多读少写的情况下使用。
condition
与synchronized中的wait、notify、notifyAll相匹配使用
在synchronized中wait对应condition中的await
在synchronized中notify对应condition中的signal
在synchronized中notifyAll对应condition中的signalAll 用法上一致,都是等待与通知。
读写锁与synchronized比较
在多线程环境中,需要对同一资源进行读写操作,同时读操作与写操作都需要进行加锁。
在使用synchronized实现上,读写互斥,但是读线程同一时间只能有一个线程可以进行读操作。
在使用读写锁实现上,读写互斥,但是读线程同一时间可以有多个线程进行读取。
在不同业务场景下正确使用锁才能提高效率,否则不仅不提高效率,反而降低效率也有可能造成死锁。