ReentrantLock(true)使用 BlockingQueue 来存储想要获取锁的线程,以FIFO方式处理。关于这一点大家都很清晰。
那么对于 'unfair locks' 或 ReentrantLock(false),它们的内部实现在哪里呢?操作系统如何决定选取哪个线程?最重要的是,现在这些线程也被存储在一个队列中吗?(它们必须在某个地方)
ReentrantLock(true)使用 BlockingQueue 来存储想要获取锁的线程,以FIFO方式处理。关于这一点大家都很清晰。
那么对于 'unfair locks' 或 ReentrantLock(false),它们的内部实现在哪里呢?操作系统如何决定选取哪个线程?最重要的是,现在这些线程也被存储在一个队列中吗?(它们必须在某个地方)
类ReentrantLock
不使用BlockingQueue
。它在幕后使用AbstractQueuedSynchronizer
的非公共子类。
AbstractQueuedSynchronizer
类,正如其文档所述,维护“先进先出(FIFO)等待队列”。这个数据结构对于公平和非公平锁是相同的。不公平并不意味着锁会改变已入队等待线程的顺序,因为这样做没有任何优势。
lock
尝试立即成功,即使有其他线程等待更长时间的锁。在这种情况下,队列甚至不涉及超车线程。这比将当前线程添加到队列中并将其置于等待状态,同时从队列中删除最长等待线程并将其状态更改为“可运行”更有效。synchronized
,某些JVM实现使用LIFO结构。这可能会随版本不同而更改(甚至在相同版本中,作为某些JVM选项或环境方面的副作用)。ReentrantLock
实现中的无参 tryLock()
也将是不公平的。这表明,不公平不是等待队列的属性,而是到达线程尝试获取新锁的处理方式。
即使此锁已被设置为使用公平的排序策略,对
tryLock()
的调用将立即获取锁(是否有其他线程正在等待锁),这种“插队”行为在某些情况下可能很有用,尽管它破坏了公平性。