【Java并发】——lock体系(二)

ReentrantLock(独占式锁)

1.重入锁的实现原理

表示能够对共享资源能够重复加锁,即当前线程获取该锁时再次获取不会被阻塞

核心方法:nonfairTryAcquire

2.公平锁的实现原理

加入hasQueuedPredecessors的逻辑判断,用来 判断当前节点在同步队列中是否有前驱节点的判断

3.非公平锁的实现原理

默认非公平锁

4.公平锁和非公平锁的比较

1.公平锁每次都是从同步队列中的第一个节点,保证请求资源时间上的绝对顺序,非公平锁有可能刚 释放锁的线程下次继续获取该锁,则有可能导致其他线程永远无法获取到锁,造成“饥饿”现象。

2.公平锁为了保证时间上的绝对顺序,需要频繁的上下文切换,而非公平锁会降低一定的上下文 切换,降低性能开销。因此,ReetrantLock默认选择的是非公平锁,保证了系统更大的吞吐量

 

ReentrantReadWriteLock(读写锁)

1.如何表示读写状态的

同步状态int类型变量state:

  • 低16位用来表示写锁的获取次数
  • 高16位用来表示读锁的获取次数

2.WriteLock的获取和释放

当ReadLock已经被其他线程获取或者WriteLock被其他线程获取,当前线程WriteLock失败;否则获取成功,支持重入性,WirteLock释放时将写状态通过CAS操作减一。

3.ReadLock的获取和释放

当WriteLock已经被其他线程获取的话,ReadLock获取失败;否则获取成功。支持重入性,通过CAS操作将读状态减1。

4.锁降级策略

按照WriteLock.lock() --> ReadLock.lock() -->WriteLock.unlock()的顺序,WriteLock会降级为ReadLock。

5.生成Condition等待队列

WriteLock可以通过newCondition方法生成Condition 等待队列,而ReadLock无法生成Condition等待队列

6.应用场景

适用于读多写少的应用场景,比如缓存设计上

 

 

Condition机制

简介:

Object的wait和notify/notifyAll是与对象监视器配合完成线程间的等待/通知机制,而Condition与 Lock配合完成等待通知机制,前者是java底层级别的,后者是语言级别的,具有更高的可控性和扩展性

1.与Object的wait/notify机制相比具有的特性

  • Condition能够支持不响应中断,而Object不支持
  • Lock能够支持多个Condition等待队列,而Object只能支持一个
  • Condition能够支持设置超时时间的await,而Object不能

2.与Object的wait/notify相对应的方法

  • 针对Object的wait方法:await,awaitNanos,....
  • 针对Object的notify/notifyAll方法:signal,signalAll方法

3.底层数据结构

复用AQS的Node类,由不带头结点的链表实现的队列

4.await实现原理

将调用await方法的线程封装成Node,尾插入到同步队列中,并通过 LockSupport.park方法将当前线程至于WAITING状态,直至其他线程 通过signal/signalAll方法将其移入到同步队列中,时期有机会在同步 队列中通过自旋获取到Lock,从而当前线程才能从await方法处退出

5.signal/signalAll实现原理

将等待队列的队头结点移入到同步队列中

6.await和signal/signalAll的结合使用

7.transient

生命周期:调用者的内存中而不会写到磁盘里持久化

原理:组织实例中的用此关键字声明的变量持久化,当对象被反序列化时,实例变量不会被持久化和恢复

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的Lock是一种更高级别的线程同步机制,它比传统的synchronized关键字更加灵活,性能也更好。Java中的Lock要求显式地获取锁和释放锁,而synchronized则会自动获取和释放锁。下面介绍一下Lock的使用及其常见的使用场景。 ### Lock的使用 Java中的Lock接口定义了一组方法,用于获取锁、释放锁以及其他一些与锁相关的操作。Lock的常用实现类有ReentrantLock、ReentrantReadWriteLock.ReadLock和ReentrantReadWriteLock.WriteLock等。 下面是一个简单的使用ReentrantLock的示例: ```java import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockDemo { private Lock lock = new ReentrantLock(); public void method() { lock.lock(); // 获取锁 try { // 这里是需要同步的代码块 } finally { lock.unlock(); // 释放锁 } } } ``` 在上面的示例中,我们使用了ReentrantLock来实现锁的功能。在需要同步的代码块前调用lock()方法获取锁,在同步代码块执行完后调用unlock()方法释放锁。 ### Lock的使用场景 Lock的使用场景与synchronized类似,都是在多线程环境下对共享资源进行同步。但是,由于Lock的灵活性更强,所以它的使用场景比synchronized更加广泛。 下面是一些常见的Lock的使用场景: - 高并发情况下的线程同步:在高并发情况下,使用Lock可以提供更好的性能,因为它的实现比synchronized更加高效。 - 读写分离的情况下的线程同步:在读写分离的情况下,使用ReentrantReadWriteLock可以实现读写锁,使得读操作可以并发执行,而写操作需要独占锁,保证数据的一致性。 - 死锁避免:在使用synchronized时,如果由于某些原因没有及时释放锁,就可能导致死锁。而使用Lock时,可以在获取锁的时候设置超时时间,避免死锁的发生。 总之,LockJava中一种强大的线程同步机制,使用时需要注意锁的获取和释放,以及异常处理等问题,但它的灵活性和性能优势使得它成为Java并发编程中不可或缺的一部分。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值