Недавно я обнаружил, что использование synchronized не предотвратит никаких мертвых блокировок.
Например. внутри этого кода:
ArrayList <Job> task;
...
public void do(Job job){
synchronized(tasks){
tasks.add(job);
}
synchronized(this){
notify();
}
}
public void run(){
while(true){
for (int = 0;i<tasks.size();i++){
synchronized(tasks){
Job job = tasks.get(i);
}
//do some job here...
}
synchronized(this){
wait(); //lock will be lost...
notifier = false; //lock will be acquired again after notify()
}
}
}
В чем проблема? Ну, а если работающий поток не ждет, то он не увидит никаких уведомлений (т.е. вызовов notify()), поэтому может попасть в мёртвую блокировку и не обработать полученные задачи! (Или он может справиться с ними слишком поздно...)
Поэтому я реализовал этот код:
private volatile boolean notifier = false;
ArrayList <Job> task;
...
public void do(Job job){
synchronized(tasks){
tasks.add(job);
}
synchronized(this){
notifier = true;
notify();
}
}
public void run(){
while(true){
for (int = 0;i<tasks.size();i++){
synchronized(tasks){
Job job = tasks.get(i);
}
//do some job here...
}
synchronized(this){
if(!notifier){
wait(); //lock will be lost...
notifier = false; //lock will be acquired again after notify()
}
}
}
}
Это правильно или я что-то упускаю? А можно проще?
BlockingQueue
- более эффективный и лучший шаблон @Marcus IMO. Вы должны хотя бы узнать о них. - person Gray   schedule 07.02.2014