若有收获,请记得分享和转发哦
使用Java进行多线程开发,使用锁是一个几乎不可避免的问题。今天,就让我们来聊一聊这个基础,但是又特别特别重要的话题。
首先,让我们来看一下,到底什么是锁? 以及,为什么要使用锁?
如果有2个线程,需要访问同一个对象User。一个读线程,一个写线程。User对象有2个字段,一个是名字,一个是手机号码。
![8f274331c4f3d5312dc467d79eaab815.png](https://i-blog.csdnimg.cn/blog_migrate/0c0502adea0a744404911e557fbe170f.png)
当User对象刚刚创建出来的时候,姓名和手机号码都是空。然后,写线程开始填充数据。最后,就出现了以下令人心碎的一幕:
![75a805bf48d5464fc73bd06d065ba4f5.png](https://i-blog.csdnimg.cn/blog_migrate/54495edddc623079a67934c2a387eb96.png)
可以看到,虽然写线程先于读线程工作,但是, 由于写姓名和写电话号码两个操作不是原子的。这就导致读线程只读取了半个数据,在读线程看来,User对象的电话号码是不存在。
为了避免类似的问题,我们就需要使用锁。让写线程在修改对象前,先加锁,然后完成姓名和电话号码的赋值,再释放锁。而读线程也是一样,先取得锁,再读,然后释放锁。这样就可以避免发生这种情况。
如下图所示:
![76d10fac0d61dc6540d8c9ba78c24453.png](https://i-blog.csdnimg.cn/blog_migrate/3bdd90283a3ee4b04c34b6ae39689298.png)
总结
可重入锁算是多线程的入门级别知识点,所以我把他当做多线程系列的第一章节,对于重入锁,我们需要特别知道几点:
对于同一个线程,重入锁允许你反复获得通一把锁,但是,申请和释放锁的次数必须一致。
默认情况下,重入锁是非公平的,公平的重入锁性能差于非公平锁
重入锁的内部实现是基于CAS操作的。
重入锁的伴生对象Condition提供了await()和singal()的功能,可以用于线程间消息通信。