为什么synchronized不够用?
    1)效率低:锁的释放情况少,试图获取锁时不能设定超时,不能中断一个正在试图获得锁的线程
    2)不够灵活(读写锁更灵活):加锁和释放的时机单一。每个锁仅有单一的条件(某个对象)
    3)无法知道是否成功获取到锁

    获取锁 :lock(), tryLock(), tryLock(long time , TimeUnit unit) 和 lockInterruptibly()
    解锁:unlock();

    四个方法的区别:
    lock() 就是最普通的获取锁,如果锁已被其他线程获取,则进行等待
    tryLock() 就是用来尝试获取锁,如果当前锁没有被其他线程占用,则获取成功,返回true,否则返回false代表获取锁失败, 相比于lock,这样的方法显然功能更强大,我们可以根据是否能获取到锁来决定后续程序的行为该方法会立即返回,即便在拿不到锁时不会一直在那等
    tryLock(long time,TimeUnit unit):超时就放弃
    lockInterruptibly():相当于tryLock(long time,TimeUnit unit)把超时时间设置为无限。在等待锁的过程中,线程可以被中断

    注意点:
    lock()方法不能被中断,这会带来很大的隐患:一旦陷入死锁,lock()就会陷入永久等待,tryLock用来避免这个问题,Lock不会像synchronized一样在异常时自动释放锁因此最佳实践是,在finally中释放锁,以保证发生异常时锁一定会被释放