ReentrantLock为啥会出现不公平的场景

阅读更多

 

 

    不公平锁产生的原因的是acquire在enqueue之前,这样后来的线程有可能会较在等待队列中的等待者之前获得锁。barging这个词可以理解为闯入,插队。不公平锁会导致某些线程总是不排队就获得锁,而同时排在队尾的线程总是出现饥饿状态。那么如何获取公平锁呢,Doug Lee页给出了方案,很简单在acquire的时候,首先检查当前线程是否在队列中(对首),如在队列中即可获得,如不在队列中,则乖乖得排在队尾睡大觉(parking)等着排在前面的线程叫醒它(unparking)。

     公平锁为啥会影响性能,从code上来看看公平锁仅仅是多了一项检查是否在队首会影响性能,如不是,那么又是在什么地方影响的?假如是闯入的线程,会排在队尾并睡觉(parking)等待前任节点唤醒,这样势必会比非公平锁添加很多paking和unparking的操作,我想这是影响公平锁性能的主要原因。

 

 

 

E文不好,不敢翻译,怕误了各位看官,还是直接贴原文吧

 

 * enqueuing, a newly acquiring thread may barge ahead of
 * others that are blocked and queued.  However, you can, if desired,
 * define tryAcquire and/or tryAcquireShared to
 * disable barging by internally invoking one or more of the inspection
 * methods, thereby providing a fair FIFO acquisition order.
 * In particular, most fair synchronizers can define tryAcquire
 * to return false if {@link #hasQueuedPredecessors} (a method
 * specifically designed to be used by fair synchronizers) returns
 * true.  Other variations are possible.
 *
 *

Throughput and scalability are generally highest for the

 * default barging (also known as greedy,
 * renouncement, and convoy-avoidance) strategy.
 * While this is not guaranteed to be fair or starvation-free, earlier
 * queued threads are allowed to recontend before later queued
 * threads, and each recontention has an unbiased chance to succeed
 * against incoming threads.  Also, while acquires do not
 * "spin" in the usual sense, they may perform multiple
 * invocations of tryAcquire interspersed with other
 * computations before blocking.  This gives most of the benefits of
 * spins when exclusive synchronization is only briefly held, without
 * most of the liabilities when it isn't. If so desired, you can
 * augment this by preceding calls to acquire methods with
 * "fast-path" checks, possibly prechecking {@link #hasContended}
 * and/or {@link #hasQueuedThreads} to only do so if the synchronizer
 * is likely not to be contended.

你可能感兴趣的:(ReentrantLock为啥会出现不公平的场景)