Interviewer: talk about the difference between fair and unfair lock lock?

Thumbs up again, a habit, micro-channel search [ Third Prince Ao propyl ] concerned people in this Internet tool Gouqietousheng.

This article GitHub github.com/JavaFamily already been included, there is a full-line manufacturers interview test sites, as well as information on my series of articles.

Foreword

The last time we mentioned the optimistic and pessimistic locking, we know that there are many types of locks, we talk about today is simple, fair and unfair lock locks the couple, and they practice in our code.

text

Before you start to talk, let me say something about their definition of both, to help you review or know about.

Fair locks: multiple threads in order to apply a lock to get a lock, the thread directly into the queue to queue, the queue is always the first to get the lock.

  • Pros: All the threads have access to resources, will not starve to death in the queue.
  • Disadvantages: Throughput will drop a lot, which in addition to the first queue thread, other threads will block, cpu blocking threads are awakened cost will be great.

Unfair lock: multiple threads to acquire the lock time, will go directly to try to get, get less, go into the waiting queue, if they can get to it directly to the lock.

  • Advantages: can reduce the CPU overhead of thread wake up, the overall efficiency will be high throughput, CPU do not have to take to wake up all threads will reduce the number of threads to evoke.
  • Cons: You may also find, and this may lead to the middle of the queue thread has acquired the lock or not for a long time not obtain a lock, leading to starvation.

I give an example to his home to talk about the plain, like a few days finally found an example of how when the day before yesterday with the three crooked go to KFC to buy breakfast queue.

Now is the time for breakfast, Ao propylene want to put forward kfc breakfast and found a lot of people, and one did not think about the past, to the tail obediently line up, so we all feel is very fair, first-served basis, so it's fair locks slightly.

That lock is unfair, Ao propylene in the past to buy breakfast and found everyone in the queue, but this bit of Ao propylene slag is like to jump the queue, then he would hate to direct the first that went to the back of eggs, rice beans are no, I do not say anything to jump the queue, only silently endured.

But occasionally, the eggs will rise, rolled lined up behind me, I am also a bully, line up quietly to the back, to jump the queue failed.

Introduction to a simple example, we might say, Jardine C, this I know ah.

我们是不是应该回归真正的实现了,其实在大家经常使用的ReentrantLock中就有相关公平锁,非公平锁的实现了。

大家还记得我在乐观锁、悲观锁章节提到的Sync类么,是ReentrantLock他本身的一个内部类,他继承了AbstractQueuedSynchronizer,我们在操作锁的大部分操作,都是Sync本身去实现的。

Sync呢又分别有两个子类:FairSync和NofairSync

他们子类的名字就可以见名知意了,公平和不公平那又是怎么在代码层面体现的呢?

公平锁:

你可以看到,他加了一个hasQueuedPredecessors的判断,那他判断里面有些什么玩意呢?

代码的大概意思也是判断当前的线程是不是位于同步队列的首位,是就是返回true,否就返回false。

我总觉得写到这里就应该差不多了,但是我坐下来,静静的思考之后发现,还是差了点什么。

上次聊过ReentrantLock了,但是AQS什么的我都只是提了一嘴,一个线程进来,他整个处理链路到底是怎样的呢?

公平锁到底公平不公平呢?让我们一起跟着丙丙走进ReentrantLock的内心世界。

上面提了这么多,我想你应该是有所了解了,那一个线程进来ReentrantLock这个渣男是怎么不公平的呢?(默认是非公平锁)

我先画个图,帮助大家了解下细节:

ReentrantLock的Sync继承了AbstractQueuedSynchronizer也就是我们常说的AQS

他也是ReentrantLock加锁释放锁的核心,大致的内容我之前一期提到了,我就不过多赘述了,他们看看一次加锁的过程吧。

A线程准备进去获取锁,首先判断了一下state状态,发现是0,所以可以CAS成功,并且修改了当前持有锁的线程为自己。

这个时候B线程也过来了,也是一上来先去判断了一下state状态,发现是1,那就CAS失败了,真晦气,只能乖乖去等待队列,等着唤醒了,先去睡一觉吧。

A持有久了,也有点腻了,准备释放掉锁,给别的仔一个机会,所以改了state状态,抹掉了持有锁线程的痕迹,准备去叫醒B。

这个时候有个带绿帽子的仔C过来了,发现state怎么是0啊,果断CAS修改为1,还修改了当前持有锁的线程为自己。

B线程被A叫醒准备去获取锁,发现state居然是1,CAS就失败了,只能失落的继续回去等待队列,路线还不忘骂A渣男,怎么骗自己,欺骗我的感情。

诺以上就是一个非公平锁的线程,这样的情况就有可能像B这样的线程长时间无法得到资源,优点就是可能有的线程减少了等待时间,提高了利用率。

现在都是默认非公平了,想要公平就得给构造器传值true。

ReentrantLock lock = new ReentrantLock(true);
复制代码

说完非公平,那我也说一下公平的过程吧:

线A现在想要获得锁,先去判断下state,发现也是0,去看了看队列,自己居然是第一位,果断修改了持有线程为自己。

线程b过来了,去判断一下state,嗯哼?居然是state=1,那cas就失败了呀,所以只能乖乖去排队了。

未命名文件 (https://tva1.sinaimg.cn/large/00831rSTly1gcxaojuen2j30oa0jxgmh.jpg)
未命名文件 (https://tva1.sinaimg.cn/large/00831rSTly1gcxaojuen2j30oa0jxgmh.jpg)

线程A暖男来了,持有没多久就释放了,改掉了所有的状态就去唤醒线程B了,这个时候线程C进来了,但是他先判断了下state发现是0,以为有戏,然后去看了看队列,发现前面有人了,作为新时代的良好市民,果断排队去了。

线程B得到A的召唤,去判断state了,发现值为0,自己也是队列的第一位,那很香呀,可以得到了。

总结:

总结我不说话了,但是去获取锁判断的源码,箭头所指的位置,现在是不是都被我合理的解释了,当前线程,state,是否是0,是否是当前线程等等,都去思考下。

鬼知道我为了画图,画了多少费稿,点个赞过分么?

课后作业

公平锁真的公平么?那什么层面不是绝对的公平,什么层面才能算公平?

我是敖丙,一个在互联网苟且偷生的工具人。

最好的关系是互相成就,各位的「三连」就是丙丙创作的最大动力,我们下期见!

文章持续更新,可以微信搜索「 三太子敖丙 」第一时间阅读,回复【资料】【面试】【简历】有我准备的一线大厂面试资料和简历模板,本文 GitHub github.com/JavaFamily 已经收录,有大厂面试完整考点,欢迎Star。

Guess you like

Origin juejin.im/post/5e7212b3f265da576e64bcd1