Lock锁的使用问题及Lock与Synchronized区别

什么是Lock?为什么需要Lock?

锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时
访问共享资源(但是有些锁可以允许多个线程并发的访问共享资源,比如读写锁).

在Lock接口出现之前,Java程序是靠synchronized关键字实现锁功能的,而Java SE 5之后,并发包中新增
了Lock接口(以及相关实现类)用来实现锁功能,它提供了与synchronized关键字类似的同步功
能,只是在使用时需要显式地获取和释放锁.

虽然它缺少了(通过synchronized块或者方法所提供的)隐式获取释放锁的便捷性,
但是却拥有了锁获取与释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字所不具备的同步特性.

使用synchronized关键字将会隐式地获取锁,但是它将锁的获取和释放固化了,也就是先获取再释放,
当然,这种方式简化了同步的管理,可是扩展性没有显示的锁获取和释放来的好

Lock锁的使用:

Lock lock = new ReentrantLock();
lock.lock(); // 加锁
try{
    // do something
}finally{
    lock.unlock(); // 解锁
}

为什么不建议将lock.lock()加锁代码放在try里面?

因为加锁操作是有可能会抛出异常的

正常情况(推荐):加锁操作在try块之前,那么出现异常时try-finally块不会执行,程序直接因为异常而中断执行

不推荐:加锁操作在try块中,由于已经执行到了try块,那么finally在try中出现异常时仍然会执行,假设此时,try中的加锁操作出现异常,finally依然会执行解锁操作,而此时并没有获取到锁,因此执行解锁操作会抛出另外一个异常,虽然都是抛出异常结束,但是此时finally解锁抛出的异常信息会将加锁的异常信息覆盖,导致信息丢失

lock.lock()能加在位于try-finally之前代码块的前面吗?能,给出理由,不能,给出原因。

不能,原因是如果try-finally之前的代码块出现异常,那么程序就不会走try-finally区域,而在异常代码块之前又进行了加锁lock.lock()操作,由于异常,程序结束,而此时之前所加的锁并没有在finally中被正常释放,那么就可能会出现死锁的情况

Lock相较Synchronized的新特性

Lock API提供的方法

猜你喜欢

转载自blog.csdn.net/weixin_43562937/article/details/107225970