2013-09-18 5 views
2

Я работаю над назначением школы, где я должен синхронизировать два потока с помощью мониторов. В этом случае каждый монитор контролирует доступ части железной дороги, и поездам необходимо запереть этот участок железной дороги, чтобы другой не мог получить к нему доступ или ему пришлось ждать, пока эта часть дорожки не станет свободной. Я никогда не использовал мониторы раньше, поэтому я уверен, что это мои ограниченные знания о том, как работают мониторы, это проблема. Поезда и их потоки работают отлично, я успешно использовал двоичные семафоры в одном и том же коде. Теперь я пытаюсь заменить семафоры мониторами.Java-монитор вместо двоичного семафора

В основном я интересуюсь, как работают условия и блокировки. Я читал на разных блогах и форумах, но, похоже, не понимаю концепцию.

Важное примечание: Мне не разрешено использовать ключевое слово synchronized.

Когда я запускаю текущий код, я получаю следующую ошибку. Ошибка возникает при occupied.signal() в методе leave:

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signalAll(AbstractQueuedSynchronizer.java:1956) 

Это код до сих пор:

public class Monitor { 

private final Lock lock = new ReentrantLock(); 
private final Condition occupied = lock.newCondition(); 

private boolean isOccupied = false; 

private int id; 

public Monitor(int id) { 
    super(); 
    this.id = id; 
} 

public void enter(){ 
    lock.lock(); 
    try { 
     if(isOccupied) 
      occupied.await(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    isOccupied = true; 
} 

public boolean tryEnter(){ 
    if(isOccupied){ 
     return false; 
    }else{ 
     enter(); 
     return true; 
    } 
} 

public void leave(){ 
    lock.unlock(); 
    isOccupied = false; 
    occupied.signal(); 
} 

} 

я бы очень признателен за любую помощь и/или идеи о том, что это не так.

Спасибо!

+1

в 'leave()', переместите 'lock.unlock()' в последнюю строку. –

ответ

2

Ваша блокировка слишком грубая. В общей схеме, если у вас есть очень исключительные обстоятельства, все блокировки должны иметь вид:

lock.lock(); 
try { 
    .... 
} finally { 
    lock.unlock(); 
} 

Вы не используете эту модель (блокировки и разблокировки в различных методах даже).

Технически проблема заключается в том, что вы сигнализируете о состоянии occupied, когда вы не держите монитор lock.

В вашей программе «эксклюзивный» замок на вашем участке трека не должен быть фактическим механизмом блокировки Java, но логическая переменная isOccupied. Измените свой код так, чтобы два метода выполнили правильную попытку ... наконец, блок, а также, вы должны переименовать свое условие как «незанятое» и отменить логику его удержания.

public void enter(){ 
    lock.lock(); 
    try { 
     while(isOccupied) 
      unoccupied.await(); 
     isOccupied = true; 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } finally { 
     lock.unlock(); 
    } 
} 


public void leave(){ 
    lock.lock(); 
    try { 
     isOccupied = false; 
     unoccupied.signal(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } finally { 
     lock.unlock(); 
    } 
} 
0

Вам не нужно использовать собственный монитор. Lock is Monitor:

public class Monitor { 

    private final Lock lock = new ReentrantLock(); 

    private int id; 

    public Monitor(int id) { 
     super(); 
     this.id = id; 
    } 

    public void enter(){ 
     lock.lock(); 
    } 

    public boolean tryEnter(){ 
     return lock.tryLock(); 
    } 
    public void leave(){ 
     lock.unlock(); 
    } 
} 
Смежные вопросы