Согласно документации Java для notify () :
Просыпается один поток, который ожидает на мониторе этого объекта. Если
все потоки ожидают этого объекта, один из них выбран
пробуждается. Выбор является произвольным и происходит по усмотрению
реализация. Поток ожидает на мониторе объекта, вызывая один
методов ожидания.
Таким образом, если вы используете synchronized(obj){}
, у вас практически нет контроля над тем, какой поток получит блокировку на obj
, и вы не можете делать никаких предположений. Это зависит от планировщика.
Если вам нужна справедливость (то есть следующий поток, получающий блокировку, является первым в очереди), взгляните на ReentrantLock : у него есть логический флаг, указывающий, что вы хотите применить справедливость.