‘fair’ 和 ‘unfair’ 锁之间的内部存储差异

huangapple go评论91阅读模式
英文:

Difference in internal storing between 'fair' and 'unfair' lock

问题

Lock 接口与 ReentrantLock(true) 类锁的工作方式是使用 BlockingQueue 来存储想要获取该 的线程。通过这种方式,先到的线程先出去,即先进先出(FIFO)。关于这一点都很清楚。

但是,“不公平锁” 呢,或者说 ReentrantLock(false) 呢?它们的内部实现是什么?操作系统如何决定现在选择哪个线程?最重要的是,这些线程现在是否也存储在队列中,还是存储在其他地方?(它们肯定得在某个地方)

英文:

The way Lock interface with class Reentrant(true) lock works is that it uses BlockingQueue to store Threads that want to acquire the lock. In that way thread that 'came first, go out first'-FIFO. All clear about that.

But where do 'unfair locks' go, or ReentrantLock(false). What is their internal implementation? How does OS decide which thread now to pick? And most importantly are now these threads also stored in a queue or where? (they must be somewhere)

答案1

得分: 9

ReentrantLock类不使用BlockingQueue。它在内部使用AbstractQueuedSynchronizer的非公共子类。

正如AbstractQueuedSynchronizer类的文档所述,它维护着“先进先出(FIFO)等待队列”。这个数据结构对于公平锁和非公平锁是相同的。非公平性并不意味着锁会改变已入队等待线程的顺序,因为这样做没有任何优势。

关键的区别在于,非公平锁允许在锁刚刚被释放时立即成功地尝试获取锁,即使有其他线程等待锁的时间更长。在这种情况下,队列甚至不会参与超越线程的操作。这比将当前线程添加到队列中并将其置于等待状态,同时将等待时间最长的线程从队列中移除并将其状态更改为“可运行”要更高效。

当线程尝试获取锁时,如果锁此时不可用,线程将被添加到队列中。此时,对于公平锁和非公平锁来说,它们之间没有区别(除了其他线程可能在不入队的情况下超越它)。由于非公平锁的顺序没有被指定,它可以在内部使用一个后进先出(LIFO)数据结构,但显然为两者只使用一个实现代码会更简单。

然而,对于不支持公平获取的synchronized,有一些JVM实现使用了LIFO结构。这可能会从一个版本变化到另一个版本(甚至在同一个版本中,作为一些JVM选项或环境因素的副作用)。

在这方面的另一个有趣的观点是,ReentrantLock实现的无参数[tryLock()]方法将是不公平的,即使锁本身处于公平模式。这表明这里不公平性并不是等待队列的属性,而是对到达的线程进行新的锁定尝试的处理方式。

> 即使此锁被设置为使用公平排序策略,对tryLock()的调用在锁可用时 将会 立即获取锁,而不管其他线程当前是否在等待该锁。即使这种“闯入”行为在某些情况下可能很有用,尽管它破坏了公平性。

英文:

The class ReentrantLock does not use a BlockingQueue. It uses a non-public subclass of AbstractQueuedSynchronizer behind the scenes.

The AbstractQueuedSynchronizer class, as its documentation states, maintains “a first-in-first-out (FIFO) wait queue”. This data structure is the same for fair and unfair locks. The unfairness doesn’t imply that the lock would change the order of enqueued waiting threads, as there would be no advantage in doing that.

The key difference is that an unfair lock allows a lock attempt to succeed immediately when the lock just has been released, even when there are other threads waiting for the lock for a longer time. In that scenario, the queue is not even involved for the overtaking thread. This is more efficient than adding the current thread to the queue and putting it into the wait state while removing the longest waiting thread from the queue and changing its state to “runnable”.

When the lock is not available by the time, a thread tries to acquire it, the thread will be added to the queue and at this point, there is no difference between fair and unfair locks for it (except that other threads may overtake it without getting enqueued). Since the order has not been specified for an unfair lock, it could use a LIFO data structure behind the scenes, but it’s obviously simpler to have just one implementation code for both.

For synchronized, on the other hand, which does not support fair acquisition, there are some JVM implementations using a LIFO structure. This may change from one version to another (or even with the same, as a side effect of some JVM options or environmental aspects).

Another interesting point in this regard, is that the parameterless tryLock() of the ReentrantLock implementation will be unfair, even when the lock is otherwise in fair mode. This demonstrates that being unfair is not a property of the waiting queue here, but the treatment of the arriving thread that makes a new lock attempt.

> Even when this lock has been set to use a fair ordering policy, a call to tryLock() will immediately acquire the lock if it is available, whether or not other threads are currently waiting for the lock. This "barging" behavior can be useful in certain circumstances, even though it breaks fairness.

huangapple
  • 本文由 发表于 2020年8月16日 05:54:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/63431161.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定