Lock 与 sychronize 简析

1.1 与 synchronized 对比

Lock 锁实现提供了比使用同步方法和语句可以获得的更广泛的锁操作。它们允许更灵活的结构,可能具有非常不同的属性,并且可能支持多个关联的条件对象。Lock 提供了比 synchronized 更多的功能。

区别:

  • Lock 非 Java 语言内置的是一个类, synchronized 是 Java 语言的关键字,incident是内置特性。
  • synchronized 不需要手动释放锁,当其修饰的部分执行完后,线程自动释放锁。Lock 必须手动释放锁,若不主动释放可能出现死锁现象。

1.2 lock 介绍

public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition()
}

1.2.1 lock和unlock与一般格式

lock() 和 unlock() 分别为上锁和解锁

一般使用格式:

Lock lock = ...;
lock.lock();
try{
    //处理的任务
}catch(Exception ex){
    
}finally{
    lock.unlock();
}

1.2.2 newCondition

相对于 synchronized 与 wait()/notify() 这两个方法一起使用可以实现等待/通知模式,Lock 锁的 newCondition() 方法返回 Condition 对象,Condition 类也可以实现等待/通知模式。

用 notify() 通知时, JVM 会随机唤醒某个等待的线程,使用 Condition 类可以进行选择性的通知。

Condition常用的两个方法:

  • await():使当前线程等待,并释放锁,其他线程调用 signal() 时,线程重新获得锁并继续执行。
  • signal():唤醒一个等待的线程。

注意:调用 Condition 的两个方法前,也需要线程持有相关的 Lock 锁,调用 await() 后线程会释放这个锁,在 signal() 调用后会从当前 Condition 对象的等待队列中唤醒一个线程,唤醒的线程尝试获得锁,一旦获得锁成功就继续执行。

1.3 ReentrantLock 类

可重入锁,是唯一实现 Lock 接口的类,并且 ReentrantLock 提供了更多的方法。

可重入锁:若线程A获取某一方法的锁后,线程B也要获取该方法的锁,假如该锁为不可重入锁,则B会进入一直等待的状态,出现自我死锁。(因此 synchronized 也是可重入锁)

ReentrantLock 类具有完全互斥排他的效果,同一时间只有一个线程在执行 ReentrantLock.lock() 方法后面的任务,这样做虽然保证了同时写实例变量的线程安全性,但效率低下。(这也是和 ReentrantReadWriteLock 类相比最主要的缺点)

因此jdk亦提供了 ReentrantReadWriteLock 类,使用它时可以在进行读操作时不需要同步执行,提升运行速度,加快运行效率。

1.4 ReadWriteLock 接口

public interface ReadWriteLock {
/**
* Returns the lock used for reading.
*/
Lock readLock();
/**
* Returns the lock used for writing.
*/
Lock writeLock();
}

一个用来获取读锁(共享锁),一个用来获取写锁(排他锁)。

即,将文件的读写操作分开,分成两个锁来分配给线程,从而使得多个线程可以同时进行读操作。

读操作:读取实际变量的值。写操作:向实例变量写入值。

**ReentrantReadWriteLock **实现了 ReadWriteLock 接口。其中有很多方法,但最重要的是 readLock() 和 writeLock() 两种方法。

读锁之间不互斥,写锁和读锁或写锁都有互斥效果。

1.5 小结

  1. Lock 是 synchronized 的进阶,完全可以取代后者,并且有更丰富的功能。
  2. Lock 是接口, synchronized 是关键字,后者是内置的语言实现。
  3. synchronized 在发生以长时,会自动释放线程占有的锁,因此不会导致死锁现象的发生;而 Lock 发生异常时,如果没有主动通过 unlock() 去释放锁,则很可能造成死锁现象,因此使用 lock 时需要在 finally 块中释放锁。
  4. Lock 可以让等待锁的线程响应中断,而 synchronized 不行,使用它的线程会一直等待下去,不能够响应中断。
  5. 通过 lock 可以知道是否成果获取锁,而 synchronized 不可以。
  6. Lock 实现读写操作分离,可以提高多个线程的读操作效率。
  7. 读读异步,读写互斥,写读互斥,写写互斥。
  8. 当资源竞争十分激烈时(大量线程同时竞争),lock 的性能远远优于 synchronized。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咀才

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值