锁的基本使用
锁一般都是实现Lock接口,所以了解Lock接口的API,基本就会用锁了。
Lock接口
方法 | 说明 |
---|---|
void lock() | 获取锁。调用方法会获取锁,直到锁获取后返回 |
void lockInterruptibly() throws InterruptedException | 可中断获取锁,在获取锁的过程中可以被中断,被中断后抛出异常返回 |
boolean tryLock() | 尝试非阻塞的获取锁,立即返回,拿到锁返回true,否则false |
boolean tryLock(long time, TimeUnit unit) throws InterruptedException | 超时的获取锁 返回的情况 1. 在超时时间内获取到了锁,返回true 2. 被中断了,抛出异常返回 3. 超时时间到,返回false |
void unlock() | 释放锁 |
Condition newCondition() | 获取等待通知组件,只有拿到了锁,才能拿到这个对象,调用wait()方法,调用后释放锁 |
带try的这种方法,就是拿的到就拿,拿不到就算了,会立即返回;这个就想学习一样,学的会就学,学不会就算了,当然这是错误的观点了。
可以看到和synchronized相比Lock要灵活和强大,使用会稍微麻烦一点:
- synchronized是隐式获取释放锁,比较简单和固定,Lock是需要手动获取锁和释放,比较灵活
- Lock可以尝试非阻塞获取锁、能被中断的获取锁、能够带超时的获取锁, synchronized不能做到
一个例子
static class Account {
// 搞个可重入锁练手
private Lock lock = new ReentrantLock();
private Integer money;
public Account(Integer money) {
this.money = money;
}
public boolean draw(int count) {
// 加锁不要放到try里边,因为如果在获取锁(自定义锁的实现)时发生了异常,异常抛出的同时,也会导致锁无故释放
lock.lock();
try {
if (money >= count) {
System.out.println("取走" + count);
money -= count;
return true;
} else {
System.out.println("钱不够了,去关注微信公号‘大雄和你一起学编程’吧");
return false;
}
} finally {
// 写到finally,保证释放锁
lock.unlock();
}
}
}