#java #multithreading #wait #synchronized #notify
#java #многопоточность #подождите #синхронизировано #уведомлять
Вопрос:
Я написал простую программу, чтобы узнать о синхронизированном блоке. Программа выглядит следующим образом:
public class SychronizedBlock {
static int balance = 0;
static Integer lock = 0;
public static void deposit(int amt) {
Thread t1 = new Thread(new Runnable() {
public void run() {
acquire_lock();
int holdings = balance;
balance = holdings amt;
System.out.println("deposit " amt ", balance: " balance);
release_lock();
}
});
t1.start();
}
public static void acquire_lock() {
synchronized(lock) {
while (lock == 1) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock = 1;
}
}
public static void release_lock() {
synchronized(lock) {
lock = 0;
lock.notifyAll();
}
}
public static void test1() {
balance = 0;
deposit(500);
deposit(500);
}
public static void main(String[] args) {
test1();
}
}
Однако при запуске программы я столкнулся с исключением IllegalMonitorStateException. Я думаю, что я поместил функции wait() и notifyAll() в синхронизированный блок, и я установил блокировку в качестве параметра synchronized . Почему у меня все еще есть исключение?
Ответ №1:
Проблема в вашем release_lock
методе. Вы переназначаете lock
значение 0
перед вызовом lock.notifyAll().
, что означает, что notifyAll будет вызываться для нового целочисленного объекта, который не заблокирован. Измените код на следующий, чтобы устранить проблему.
public static void release_lock() {
synchronized(lock) {
lock.notifyAll();
lock = 0;
}
}
Комментарии:
1. Или лучше, просто избегайте изменения
lock
переменной. Очень редко — если вообще когда-либо — хорошая идея синхронизировать переменную, которая может измениться. (Я бы также избегал использованияInteger
блокировок for из-за эффекта кэширования. Обычно я предпочитаю блокировать равнинуObject
, которая используется только для этой цели.)2. Получите это! Большое спасибо за ваше четкое объяснение! Я не понимал, что оператор «lock = 0» раньше назначит новый объект для блокировки.