Polegares para cima de novo, um hábito, pesquisa micro-canal [ Terceiro príncipe Ao propil ] pessoas envolvidas nesta ferramenta Internet Gouqietousheng.
Este artigo GitHub github.com/JavaFamily já foi incluído, há uma linha completa locais de teste fabricantes de entrevista, bem como informações sobre minha série de artigos.
prefácio
A última vez que mencionou o bloqueio otimista e pessimista, sabemos que existem muitos tipos de fechaduras, falamos de hoje é simples, justo e injusto bloqueio bloqueia o casal, e eles praticam em nosso código.
texto
Antes de começar a falar, deixe-me dizer algo sobre a sua definição de ambos, para ajudá-lo a rever ou conhecer.
fechaduras Fair: vários segmentos, a fim de aplicar um bloqueio para obter um bloqueio, o fio diretamente na fila para fila, a fila é sempre o primeiro a obter o bloqueio.
- Prós: Todos os tópicos têm acesso a recursos, não vai morrer de fome na fila.
- Desvantagens: Rendimento vai cair muito, o que, além do primeiro segmento fila, outros segmentos irão bloquear, cpu bloqueando tópicos são custo despertado será grande.
bloqueio injusto: vários segmentos de adquirir o tempo de bloqueio, irá diretamente para tentar obter, receber menos, ir para a fila de espera, se eles podem obtê-lo diretamente para o bloqueio.
- Vantagens: pode reduzir a CPU sobrecarga de rosca acordar, a eficiência global será alto rendimento, CPU não tem que tomar para acordar os tópicos irá reduzir o número de threads de evocar.
- Contras: Você também pode encontrar, e isso pode levar para o meio do fio fila adquiriu o bloqueio ou não por um longo tempo não obter um bloqueio, levando a fome.
Dou um exemplo para sua casa para falar sobre a planície, como alguns dias finalmente encontrado um exemplo de como, quando anteontem com os três Crooked ir para KFC para comprar fila de pequeno-almoço.
Agora é o momento para o pequeno almoço, Ao propileno quer colocar-almoço KFC frente e encontrou um monte de gente, e uma não pensar sobre o passado, para a cauda obedientemente line up, de modo que todos nós sentimos é muito justo, primeiro a ser servido, por isso é fechaduras justas ligeiramente.
Esse bloqueio é injusto, Ao propileno no passado para comprar café da manhã e encontrou todos na fila, mas esse pouco de Ao propileno escória é como furar a fila, então ele odiaria para dirigir a primeira que foi para o fundo de ovos, feijão arroz são não, eu não disse nada para furar a fila, única silenciosamente suportou.
Mas, ocasionalmente, os ovos vão subir, rolou alinhados atrás de mim, eu também sou um tirano, se alinham em silêncio para trás, para furar a fila falhou.
Introdução a um exemplo simples, podemos dizer, Jardine C, isso eu sei 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就失败了呀,所以只能乖乖去排队了。
线程A暖男来了,持有没多久就释放了,改掉了所有的状态就去唤醒线程B了,这个时候线程C进来了,但是他先判断了下state发现是0,以为有戏,然后去看了看队列,发现前面有人了,作为新时代的良好市民,果断排队去了。
线程B得到A的召唤,去判断state了,发现值为0,自己也是队列的第一位,那很香呀,可以得到了。
总结:
总结我不说话了,但是去获取锁判断的源码,箭头所指的位置,现在是不是都被我合理的解释了,当前线程,state,是否是0,是否是当前线程等等,都去思考下。
鬼知道我为了画图,画了多少费稿,点个赞过分么?
课后作业
公平锁真的公平么?那什么层面不是绝对的公平,什么层面才能算公平?
我是敖丙,一个在互联网苟且偷生的工具人。
最好的关系是互相成就,各位的「三连」就是丙丙创作的最大动力,我们下期见!
文章持续更新,可以微信搜索「 三太子敖丙 」第一时间阅读,回复【资料】【面试】【简历】有我准备的一线大厂面试资料和简历模板,本文 GitHub github.com/JavaFamily 已经收录,有大厂面试完整考点,欢迎Star。