在使用synchronized时,Java如何确定应该继续哪个线程?

时间:2013-11-21 11:54:23

标签: java multithreading concurrency synchronization queue

private static void WaitInQueue(Customer c)
{         
    synchronized(mutex){
       //Do some operation here.
    }              

}

我需要让线程在继续之前等待(一次只有一个),但是,似乎synchronized不使用FIFO来确定接下来应该继续进行。(看起来像LIFO)为什么会这样?

如何确保在synchronized时等待的第一个线程是第一个获取锁定的线程?

4 个答案:

答案 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