简要对比:
Lock | Synchronized | |
---|---|---|
性能 | 大量并发适用 | 大量并发时候性能急剧下降,适用于少量并发 |
存在层次 | 应用级,Java中一个接口 | 系统级,Java中的关键字 |
锁的释放 | 必须在finally块中释放锁,不然容易产生死锁 | 1、JVM 执行完同步代码 2、发生异常,系统释放锁 |
锁的获取 | 有多种获取方式,可设置在等待一段时间后如果没有获得锁则放弃请求 | 没有获得锁则会一直阻塞等待 |
出现中断 | 可以让等待锁的异常响应中断 | 无法响应中断,将会一直阻塞下去 |
出现异常 | 如果不用unlock()释放锁,容易出现死锁,因此必须在finally块中释放锁 | 系统会自己释放锁 |
锁的状态 | 无法判断是否中断和获得锁 | 可以判断 |
锁的类型 | 可重入,可中断,可为公平锁(也可非公平锁) | 可重入,不可中断,非公平 |
注:
Lock的获取方式:
源自Lock接口里面定义的四个函数:
lock():先获取锁,取得锁之后再看看是否有请求将其设置为中断状态;
tryLock();
tryLock(long, TimeUnit)
lockInterruptibly():先看是否有请求将其设置为中断状态,之后再尝试获取锁;
lockInterruptibly()方法比较特殊,当通过这个方法去获取锁时,如果其他线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。也就使说,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。<.br>
详细区别:
ReentrantLock.lockInterruptibly允许在等待时由其它线程调用等待线程的Thread.interrupt方法来中断等待线程的等待而直接返回,这时不用获取锁,而会抛出一个InterruptedException。
ReentrantLock.lock方法不允许Thread.interrupt中断,即使检测到Thread.isInterrupted,一样会继续尝试获取锁,失败则继续休眠。只是在最后获取锁成功后再把当前线程置为interrupted状态,然后再中断线程