简介
Lock是一种用于控制多个线程对共享资源访问的工具,是用来实现线程同步的一种机制。
Lock接口有着与synchronized关键字相似的功能(定义了同步相关的方法及规则,子类来实现),不过它比synchronized更灵活、更强大,它提供了一些synchronized不具备的方法(例如:可中断)。
通常情况下,锁提供对共享资源的独占访问(独占锁,即一次只有一个线程能获取锁),并且对共享资源的所有访问都必须先获取到锁。但是,有些锁也可能允许对共享资源的并发访问(共享锁,例如ReadWriteLock中的读锁)。
方法
Lock接口定义了以下方法:
方法 | 描述 |
lock | 获取锁。如果锁不可用(即获取锁失败),当前线程处于线程调度的目的将被禁用,并处于休眠状态,直至获取到锁,且在锁获取时无法被中断 |
lockInterruptibly | 获取锁。与lock方法一样,只是会在线程被标记中断时停止获取锁 |
tryLock | 尝试获取锁。如果锁不可用,会立即返回失败 |
tryLock(long time,TimeUnit timeUnit) | 尝试获取锁。与lockInterruptibly方法类似,只是额外增加了超时中断锁获取的操作 |
unlock | 释放锁 |
newCondition | 创建一个绑定此Lock的Condition实例。Conditio的具体操作依赖于Lock实现,且在调用Condition的方法时需先获取到锁 |
Lock是一个接口,它里面定义了锁相关的方法,子类需根据它定义的规则去实现。
目前来说,锁相关的核心逻辑都是由AQS来实现的,具体的Lock子类提供入口方法及自定义加锁逻辑配合AQS一起来实现整个锁相关的逻辑代码
对比
Lock与synchronized的对比:
- synchronized是java内置的关键字,Lock是一个接口
- synchronized不能响应中断(会一直等待直至获取到锁),Lock可响应中断(提供了多个方法,可以通过线程标识中断或超时来停止锁的获取)
- synchronized会自动释放锁(执行完同步代码块或发生异常时),Lock必须手动调用unlock释放锁,否则会出现死锁,所以一般在finally中调用unlock
- synchronized是非公平锁(不能保证等待锁的线程的顺序),Lock可以实现公平锁或非公平锁(例如:ReentrantLock)
- synchronized和Lock都是可重入锁
- Lock还可以支持多个Condition(条件队列)
总的来说,就是Lock提供了更多样性更灵活的加锁方式,而synchronized使用起来更方便