2015-05-20 3 views
3

Я прочитал документ оракула о синхронизированных методах и о том, как они могут ввести блокировку в многопоточную программу, но есть одна вещь, которая неясна для меня. Являются ли последующие вызовы уже заблокированным методам в очереди?делать синхронизированные вызовы очереди java?

Допустим, у нас есть класс:

class Astore { 
    ... 
    public synchronized void a() { 
     doSomethingTimeConsuming(); 
    } 
    ... 
} 

и 3 нити, которые называют astore.a()

final Astore astore = new Astore(); 

Thread t1 = new Thread(new Runnable() { 
    public void run() { 
     astore.a(); 
     doSomethingElse(); 
     astore.a(); 
    } 
}); 
t1.start(); 

Thread t2 = new Thread(new Runnable() { 
    public void run() { 
     astore.a(); 
    } 
}); 
t2.start(); 

Thread t3 = new Thread(new Runnable() { 
    public void run() { 
     astore.a(); 
    } 
}); 
t3.start(); 

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

Будет ли порядок операций храниться в очереди, так что нити, призывающие будет:

  1. t1 (как его называли первым)
  2. t2 (был вызван после того, как T1)
  3. t3
  4. t1 снова (он был занят чем-то с A уже в то время как другие потоки запрошенный метод)

Могу ли я с уверенностью предположить, что будет б (или, что еще хуже, t2 и t3 могут быть вызваны в случайном порядке)

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

+0

'Какая наилучшая практика, когда нескольким потокам может потребоваться совместное использование данных (например, сервер сокетов с одним потоком для каждого активного соединения? Это вопрос в миллиард долларов.Целые библиотеки могут быть заполнены книгами только по одному предмету. Более конкретный вопрос с большей вероятностью будет дан. – biziclop

+1

В конкретном случае, о котором вы спрашивали, вам необходимо уменьшить размер вашего куска и/или отделить процессы загрузки и импорта. – chrylis

+0

... или если структура данных огромна, вы можете сохранить ее в базе данных в любом случае, и в этот момент мы говорим об обработке транзакций. – biziclop

ответ

8

Нет, он не будет звонить в очередь на вызовы метод.

Если вызов выполнен из потока, который уже имеет блокировку (например, рекурсивный вызов), тогда он будет действовать как обычно.

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

Заказ не гарантируется, пожалуйста, используйте fairReentrantLock если это важно.

+0

Итак, другие потоки будут ждать ... вроде бы подождать в очереди? – Kayaman

+1

Нет, нет упорядоченной очереди. Я отредактировал свой ответ, чтобы уточнить. – folkol

+0

@Kayaman Они будут ждать, но не в упорядоченной очереди, просто расхаживая вокруг, и планировщик может выбрать любой из них, когда монитор станет доступен. – biziclop

2

Если вы используете ReneterantLock вместо синхронизированного блока есть параметр справедливости, что вы можете установить так, чтобы поток, который ждет большинство получает блокировку, когда блокировка снимается другим потоком, Вы можете прочитать больше here

+0

Просто отметить; синхронизированные блоки также являются реентерабельными. – zgulser

0

folkol верно.

На самом деле его зависит от конструкции машины (CPU)

Абоненты должны ждать, пока ресурс не был наделен процессором. Затем ЦПУ случайно выбирает одного из следующих абонентов и выделяет для него ресурс и блокирует его (из-за синхронности), пока второй вызывающий абонент не завершит свое задание.

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