2013-11-21 2 views
1
private static void WaitInQueue(Customer c) 
{   
    synchronized(mutex){ 
     //Do some operation here. 
    }    

} 

Мне нужно, чтобы потоки ожидали, прежде чем продолжить (только по одному), однако, похоже, что синхронизированный не использует FIFO для определения того, что следует делать дальше. (Кажется, это LIFO). Почему это?Как Java определяет, какой поток должен выполняться при использовании синхронизации?

Как я могу гарантировать, что первый поток, который будет ждать в синхронизированном состоянии, будет первым, кто сможет продолжить блокировку?

+1

Я думаю, планирование нити позаботятся базовой операционной системы. –

+0

Java не пытается заказать, это по сути случайное. – zapl

+0

использовать очередь для обеспечения честности синхронизации. – bsiamionau

ответ

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() 
    } 
    } 

внимание, однако, что это приводит к общему снижению производительности и поэтому не рекомендуется. цитаты из документации»

Конструктора для этого класса принимает необязательный параметр справедливости. Когда истинно, при раздоре, замки выступают за предоставление доступа к дольше ожиданию потока. В противном случае эта блокировка не гарантирует . частности порядок доступа к программам с использованием справедливой замки, доступ многих потоков может отображать более низкую общую пропускную способность (т.е. медленнее, часто гораздо медленнее), чем те, которые используют настройки

+0

Не гарантируя какой-либо конкретный порядок и выбор наугад - это совершенно разные понятия. –

+0

@MarkoTopolnik - youre правый. я исправил свой ответ – radai

0

Вы можете использовать класс Semaphore с установленным значением справедливости и значением 1. Это гарантирует порядок FIFO для потоков и почти идентичен синхронизированному блоку.

ReentrantLock также обеспечивает справедливость.

-1

Вы должны использовать Thread.jo по умолчанию в ожидании, прежде чем продолжить. Просто пройти по следующей ссылке http://msdn.microsoft.com/en-us/library/dsw9f9ts(v=vs.90).aspx

+2

Это не очень хорошая идея, и это сделало бы код излишне сложным. – Kayaman

0

Чтобы ответить «Почему это?»: Там редко какая-либо причина использовать определенный порядок на замке. Нити попадают в замок в случайном порядке и могут также оставить его таким же образом. Важная вещь с точки зрения JVM заключается в том, чтобы держать ядра занятыми, работая над кодом вашей программы. Как правило, если вы заботитесь о том, в каком порядке работают ваши потоки, вам нужно что-то гораздо более интересное, чем блокировка или семафор.

Единственное хорошее исключение, о котором я могу думать, - это то, что ваша блокировка всегда имеет ожидающие потоки, создавая реальную возможность того, что поток, который попадает в нее, может ждать много секунд, постоянно натыкаясь на заднюю часть «очереди», , в то время как разгневанный пользователь испаряется. Тогда FIFO имеет большой смысл. Но даже здесь вы можете потратить некоторое время, пытаясь ускорить синхронизированный блок (или избежать его полностью), поэтому большинство потоков, которые его ударили, не блокируются.

В целом, думаю, долго и упорно о вашем дизайне, если вы найдете себе беспокоиться о порядке ваши потоки выполняются в.

Смежные вопросы