Пусть есть разделяемый ресурс в программе "res". Пусть есть два потока, которые хотят зайти в критическую секцию:
void Meth(...){
... //Что нужно написать, чтобы на консоль вывелось сообщение, что тред (threadName) ждёт, когда
synchronized (res)//Здесь разделяемый ресурс
{
//some code
}
}
Я реализовал вот так, всё работает (имхо) но у меня большие сомнения:
Class Resource {
boolean isBusy = false; //Флаг который бы переключался, если объект ресурса захватывался.
}
class A extend Thread{
String name;
static Resource res = new Resource(); //Создал объект ресурса
void Meth() throws InterruptedException {
try{
while(res.isBusy==true){
System.out.println("Потоку " + this.name + " приходится подождать.");
Thread.currentThread().sleep(7);
}
synchronized (res)//Здесь разделяемый ресурс
{
res.isBusy = true;
... //some code
res.isBusy = false;
}
catch (Exception e){ e.printStackTrace();}
}
}
Нормальна ли такая реализация, если десяток потоков периодически ждёт пока освободится критическая секция, и в процессе ожидания они должны сообщить программисту, что ждут? У меня сомнения в корректности, потому что я делаю опрос занятого объекта, пытаясь прочитать его поле. Так точно можно делать, не боясь что программа вылетит?
Есть ли ещё какая-нибудь обще принятая реализация в java вывода сообщения о том, что поток не может зайти в блок синхронайзед, потому что ждёт освобождения?
Если прям нужно сообщать, то "критическую секцию" можно обернуть не в synchronized
, а в
ReentrantLock lock = new ReentrantLock();
...
while(!lock.tryLock()) {
print_message_and_sleep();
}
try{
run_critical_section();
} finally {
lock.unlock()
}
Но вообще, res.isBusy = true;
-- такой подход явно не из java, поэтому если бы вопрос был более конкретным, можно было бы сделать лучше, как для читаемости-поддерживоемости кода, так и с точки зрения быстродействия. В java есть много способов и читать, и менять поле объекта вообще без блокировок.
Есть ли ещё какая-нибудь обще принятая реализация в java вывода сообщения о том, что поток не может зайти в блок синхронайзед, потому что ждёт освобождения?
нет, потому что обычно либо так не делают (блокируют более мелкие операции, чтобы потоки друг друга не ждали); либо, если по смыслу задачи, они должны так долго ждать, тогда вероятно есть смысл переорганизовать работу с этим ресурсом (например, чтобы управляющий поток без синхронизации работал с ресурсом, и раскидывал задачи остальным потокам,а они работали параллельно без блокировки на ресурсе)
Для начала минусы вашего кода
isBusy
должно быть объявлено как volatile
иначе при чтении значения этого поля вне блока synchronized
можно прочитать некорректное значениеisBusy
, но до входа в секцию synchronized
Все эти проблемы решаются заменой секции synchronized
на объект ReentrantLock
ReentrantLock lock = new ReentrantLock();
...
// проверяем захвачен ли ресурс. Если нет, то захватываем его
if (!lock.tryLock()) {
// Если не удалось захватить сразу, то организовываем цикл
do {
System.out.println("Потоку " + this.name + " приходится подождать.");
// Пытаемся захватить блокировку сами, но уже ждем разблокировки 100 миллисекунд
} while (!lock.tryLock(100, TimeUnit.MILLISECONDS)); // крутим цикл, пока не захватим ресурс
}
try {
run_critical_section();
} finally {
lock.unlock()
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
userDAO:
Вопрос вот в чем: Есть класс Controller и FXMLУ кнопки "бросить кубик" есть event onMouseClicked выполняющий метод thrw() в Controller