童话里美好的时光.png条条大路通罗马,但有人生在罗马,但时间最公平,没有人浪费的起
- Lock 接口
锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源(当然,有些锁可以允许多个线程同时访问某个共享资源,比如读写锁)。在Lock接口出现之前,Java程序是靠Synchronized关键字来实现锁得功能的,而在Java SE 5之后,并发包中新增了Lock 接口(以及相关的实现类)来实现锁的功能,它提供了与Synchronized关键字相似的同步功能,只是在使用时需要显示获取和释放。虽然它缺少了隐式获取释放锁的便携性,但是却拥有了锁的获取和释放的可操作性,可中断的获取锁以及超时获取锁等多种Synachronized关键字所不具备了同步特性。
使用Synchronized关键字将会隐式的获取锁,但是他将锁的获取和释放固化了,也就是先获取再释放。当然这种方式简化了同步的管理,但是牺牲了显示获取锁的可拓展性。例如,针对一个场景,手把手进行锁的获取和释放,先获取A锁,然后获取B锁,当获取B锁后,释放锁A然后同时获取锁C,当获取到锁C后释放锁B的同时获取锁D,依次类推,在这种场景下,Synchronized关键字就不那么容易实现了,而使用Lock却容易的多。
Lock的使用也是很简单的,实例代码如下:
Lock lock = new ReentrantLock();
lock.lock();
try{
//TOO-DO
}finally{
lock.unlock();
}
在finally中释放锁,目的是为了保证获取锁之后,最终锁能够获得释放。
不要将锁的获取放到try代码块里面去,因为如果获取锁的过程中失败了,异常将会抛出,这个时候所可能根本就没有获取,而finally中却又在释放锁。
Lock接口提供Synchronized关键字所不具备的主要特性如下表所示:
特性 | 描述 |
---|---|
尝试堵塞地获取锁 | 当线程尝试获取锁的时候,如果这个这一时刻锁没有被没有其他线程获取,则成功获取这个锁 |
能被中断地获取锁 | 与Synchronized不同,获取到锁的线程能够响应中断,当获取到锁的线程被中断时,中断异常将会被抛出,同时锁会被释放 |
超时地获取锁 | 在指定的截至时间之前获取锁,如果截止时间到了任然无法获取锁,则返回 |
Lock是一个接口,它定义了锁的获取和释放基本操作,LOCk的API如下表所示:
方法名称 | 描述 |
---|---|
void lock() | 获取锁,调用该方法当前线程将会获取锁,当锁获取后,从该方法返回 |
void lockInterruotibly() throws InterruptedException | 可中断地获取锁,和lock()方法不同的是该方法可以响应中断,当获取到锁的线程被中断时,中断异常将会被抛出,同时锁会被释放 |
boolean tryLock() | 尝试非堵塞的获取锁,和lock()方法的不同之处就是该方法会立刻返回,如果获取到了,就返回true,否则返回false |
boolean tryLock(long time,TimeUnit unit) throws InterruptException() | 超时获取锁,当前线程会在以下3种情况下返回:1). 当前线程在超时时间内获取锁 2). 当前线程在超时时间内被中断 3). 超时时间结束,返回false |
void unLock() | 释放锁 |
Condition newCondition() | 获取等待通知组件,该组件和当前的锁绑定,当前线程只有获取到了锁才能调用组建的await()方法,而调用之后,当前线程释放锁。 |
这里先简单介绍一下Lock接口的API,随后会详细地介绍同步器AbstractQueuedSynchronizer以及常用的Lock接口的实现。Lock接口的实现基本上是通过聚合一个队列同步器的子类来实现线程的访问控制的。
网友评论