Я прочитал документ оракула о синхронизированных методах и о том, как они могут блокировать многопоточную программу, но есть одна вещь, которая мне неясна. Поступают ли в очередь последующие вызовы уже заблокированных методов?
Допустим, у нас есть класс:
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();
Я не уверен, правильно ли я сделал пример, но дело в том, что 3 потока почти одновременно вызывают один и тот же объект с помощью синхронизированного метода.
Будет ли порядок операций сохранен в очереди, чтобы вызываемые потоки были:
- t1 (так его называли первым)
- t2 (был назван после T1)
- t3
- t1 снова (он уже был занят чем-то с A, пока другие потоки запрашивали метод)
Могу ли я с уверенностью предположить, что это будет поведение, или нет гарантии, что это будет порядок (или, что еще хуже, t2 и t3 могут быть вызваны в случайном порядке)
Какова лучшая практика, когда нескольким потокам может потребоваться обмен данными (например, сервер сокетов с одним потоком для каждого активного соединения - я не хочу, чтобы 6 клиентов истекали по тайм-ауту, ожидая, пока первый завершит огромную загрузку в общая структура данных)
What is the best practice when multiple threads may need to share data (for instance a socket server with one thread for each active connection
Это вопрос на миллиард долларов. Целые библиотеки могут быть заполнены книгами только по этому предмету. Вероятнее всего, будет дан ответ на более конкретный вопрос. - person biziclop   schedule 20.05.2015doSomethingTimeConsuming()
- ошибка. Одно из важнейших советов, которым вы можете следовать, - старайтесь, чтобы вашиsynchronized
блоки были как можно меньше. Настоящее искусство многопоточного программирования состоит в том, чтобы спроектировать вашу программу так, чтобы ее потоки не тратили время на ожидание друг друга, когда есть работа, которую они могут выполнять. Если ваша программа выполняет какие-либо операции ввода-вывода внутри блокаsynchronized
или синхронизированный блок обновляет больше переменных, чем вы можете сосчитать на пальцах, тогда вы можете пересмотреть свой дизайн. - person Solomon Slow   schedule 20.05.2015t1
вызоветastore.a()
до того, как его вызовет какой-либо из двух других потоков. Каждый из трех вызововstart()
создает новый поток и делает его работоспособным. Но runnable - это не то же самое, что run. Вполне возможно, что все три вызоваstart()
завершатся до того, как какой-либо из новых потоков действительно начнет работать, и операционная система полностью решает, в каком порядке они будут запускаться. - person Solomon Slow   schedule 20.05.2015