private static void WaitInQueue(Customer c)
{
synchronized(mutex){
//Do some operation here.
}
}
我需要让线程在继续之前等待(一次只有一个),但是,似乎synchronized不使用FIFO来确定接下来应该继续进行。(看起来像LIFO)为什么会这样?
如何确保在synchronized时等待的第一个线程是第一个获取锁定的线程?
答案 0 :(得分:2)
同步块不保证公平性 - 理论上可以选择执行任何等待线程。如果你真的想要一个公平的锁(fifo),切换到使用java 5+中引入的更新的锁定机制。 例如,参见documentation for ReentrantLock。 在这里你是如何使用公平锁定的:
private final ReentrantLock lock = new ReentrantLock(true); //fair lock
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
但请注意,这会导致整体性能下降,因此不建议这样做。
引用文献"
此类的构造函数接受可选的fairness参数。 当设置为true时,在争用下,锁有利于授予访问权限 最长等待的线程。否则此锁不保证任何 特定的访问顺序。使用公平锁的程序由许多人访问 线程可以显示较低的总吞吐量(即,较慢;通常 比使用默认设置
的那些慢得多
答案 1 :(得分:0)
您可以使用Semaphore类,公平性设置为true,计数为1.这保证了线程的FIFO顺序,并且几乎与同步块相同。
ReentrantLock
也提供了公平性设置。
答案 2 :(得分:0)
回答“为什么会这样?”:很少有理由在锁上使用特定订单。线程以随机顺序击中锁定,并且可以以相同的方式保留它。从JVM的角度来看,重要的是让核心忙于处理程序的代码。一般来说,如果你关心你的线程运行的顺序,你需要比锁或信号量更多的东西。
我能想到的唯一一个很好的例外是,如果你的锁总是有等待的线程,那么创建一个真正的可能性,一个击中它的线程可能会等待很多秒,不断被撞到后面“队列”,而愤怒的用户会发烟。然后,FIFO很有意义。但即使在这里你也可能想花一些时间来尝试加速同步块(或者完全避免它),这样点击它的大多数线程都不会被阻塞。
总而言之,如果您发现自己担心线程的运行顺序,请仔细考虑您的设计。
答案 3 :(得分:-1)
在继续之前,您应该使用Thread.join进行等待。 只需浏览以下链接即可 http://msdn.microsoft.com/en-us/library/dsw9f9ts(v=vs.90).aspx