> For the complete documentation index, see [llms.txt](https://yibingxiong.gitbook.io/java-concurrent-programming-art-mini/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yibingxiong.gitbook.io/java-concurrent-programming-art-mini/di-03-zhang-suo/01-suo-de-ji-ben-shi-yong.md).

# 01-锁的基本使用

锁一般都是实现Lock接口，所以了解Lock接口的API，基本就会用锁了。

## Lock接口

| 方法                                                                    | 说明                                                                                    |
| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| void lock()                                                           | 获取锁。调用方法会获取锁，直到锁获取后返回                                                                 |
| void lockInterruptibly() throws InterruptedException                  | 可中断获取锁，在获取锁的过程中可以被中断，被中断后抛出异常返回                                                       |
| boolean tryLock()                                                     | 尝试非阻塞的获取锁，立即返回，拿到锁返回true，否则false                                                      |
| boolean tryLock(long time, TimeUnit unit) throws InterruptedException | <p>超时的获取锁<br>返回的情况<br>1. 在超时时间内获取到了锁，返回true<br>2. 被中断了，抛出异常返回<br>3. 超时时间到，返回false</p> |
| void unlock()                                                         | 释放锁                                                                                   |
| Condition newCondition()                                              | 获取等待通知组件，只有拿到了锁，才能拿到这个对象，调用wait()方法，调用后释放锁                                            |

带try的这种方法，就是拿的到就拿，拿不到就算了，会立即返回；这个就想学习一样，学的会就学，学不会就算了，当然这是错误的观点了。

可以看到和synchronized相比Lock要灵活和强大，使用会稍微麻烦一点：

1. synchronized是隐式获取释放锁，比较简单和固定，Lock是需要手动获取锁和释放，比较灵活
2. Lock可以尝试非阻塞获取锁、能被中断的获取锁、能够带超时的获取锁， synchronized不能做到

## 一个例子

```java
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();
        }
    }
}
```
